Skip to content
Go To Dashboard

Repositories

Repositories let a deployed agent create and manage Git repositories for durable code and artifacts. Agent steps call the typed ctx.sapiom.repositories capability; Sapiom supplies the authenticated cloud connection when the deployed agent runs.

The intended write path is agent-managed: give a repository handle to a coding run, then publish that sandbox checkout with repository.pushFromSandbox(...).

What the agent needsRecommended operation
A new durable repositoryrepositories.create(slug)
An existing repository handlerepositories.get(slug)
The tenant’s repositoriesrepositories.list()
Publish a sandbox checkoutrepository.pushFromSandbox(sandbox, options)
Remove a repositoryrepositories.delete(slug) or repository.delete()

Use a repository when files must survive an ephemeral coding or compute sandbox. The repository remains until it is deleted; sandbox cleanup does not remove it.

const repo = await ctx.sapiom.repositories.create(input.repoSlug);
const coding = await ctx.sapiom.models.coding.run({
task: input.task,
gitRepository: repo,
keepSandbox: true,
});
try {
if (coding.status !== "completed" || !coding.result?.success) {
throw new Error(
coding.error?.message ?? `Coding run ${coding.status}`,
);
}
const pushed = await repo.pushFromSandbox(coding.sandbox, {
message: `agent: ${input.changeSummary}`,
});
if (!pushed.pushed) {
throw new Error("Repository push did not complete");
}
return {
repoSlug: repo.slug,
sha: pushed.sha,
branch: pushed.branch ?? null,
};
} finally {
await coding.sandbox.destroy().catch((error) => {
ctx.logger.warn("coding sandbox cleanup failed", {
sandbox: coding.sandbox.name,
error: String(error),
});
});
}

When a coding run receives gitRepository: repo, its checkout lives at /workspace/<slug> by default. pushFromSandbox commits any pending changes and pushes the current commit. Pass workingDirectory only when the checkout is elsewhere.

Repository creation succeeds before the coding work begins. Decide whether a failed run should leave the empty or partial repository for inspection or delete it as compensating cleanup.

const repositories = await ctx.sapiom.repositories.list();
const target = repositories.find((repo) => repo.slug === input.repoSlug);
if (!target) return { deleted: false, reason: "not-found" };
await target.delete();
return { deleted: true, repoSlug: target.slug };

create, get, and list return method-capable Repository handles. Pass a slug between independent steps and call get in the step that needs a fresh handle; do not serialize a live handle and assume its methods survive a process boundary.

Local Run returns method-capable repository and sandbox fixtures. It does not create a Git repository, run a coding model, commit files, or push a branch.

Namespace overrides use plural paths; handle-method overrides use the singular handle name:

{
"version": 1,
"steps": {
"build-project": {
"repositories.create": {
"slug": "site-local",
"cloneUrl": "https://git.invalid/site-local.git",
"status": "active"
},
"repository.pushFromSandbox": {
"pushed": true,
"sha": "abc123fixture",
"branch": "main"
}
}
}
}

The built-in models.coding.run stub supplies a method-capable sandbox to the example path. Override it separately when the step branches on coding output. After the run, assert the terminal result and require both unusedStubs and stubWarnings to be empty. A passing Local Run does not prove Git persistence, coding quality, sandbox contents, or a production push.

List before creating when the workflow should reuse a known slug, make retry behavior explicit, and delete repositories only when their durable history is no longer needed. Keep sandbox cleanup separate from repository retention.

Use the signed-in capability catalog for current availability, limits, and pricing. Repository operations and the coding run that writes the repository have distinct lifecycles and usage.