Custom agents reference
Every field, tool and limit of a custom agent. To write your first agent, see Custom agents.
The fields of an agent
| Field | Required | What it is |
|---|---|---|
agent | Yes | A TanStack AI agent: defineAgent({ name, description, run }) from @tanstack/ai. Its description shows on the settings page. |
on | Yes | The events that start it: issue.opened, pull.opened, pull.pushed, label.added. |
trigger | Yes | Who starts it. See below. |
budget | Yes | maxTokens from 1 to 2,000,000. maxCostCents is optional, for a provider that reports a cost. |
model | No | { provider, model }, for ctx.forge.model(). Without it, the agent uses Workers AI. |
secrets | No | Names of repository CI secrets. See MCP servers and secrets. |
egress | No | The https hosts that the agent can reach, such as mcp.linear.app. |
permissions | No | { contents: 'write' } gives the tools that change a branch. See Agents that change code. |
A trigger is one of these:
{ on: 'off' }{ on: 'everyone' }{ on: 'role', min: 'triage' }, withread,triage,write,maintainoradmin{ on: 'label', label: 'needs-docs' }
With label.added and a label trigger, the agent starts when a person adds that label.
ctx.forge
The run of your agent gets ctx.forge from the forge:
| Member | What it is |
|---|---|
model() | A TanStack AI text adapter for chat(). The forge calls the model with the key, and counts the tokens against budget. With outputSchema, chat() gives back JSON that matches the schema. |
item | The issue or pull request: kind, number, title, author and labels. A pull request also has pull.headRef and pull.headCommit. |
agent | The name of the agent in the factory file. |
tools | The forge tools that this run can call. Pick them with forgeTools. |
ctx.messages holds one message: the issue or pull request, and its comments, as data that the model must not obey.
The forge tools
Get them with forgeTools(ctx, [...]) from @tanstack-source/ci/agent:
| Tool | What it does |
|---|---|
read_file, list_files, search, diff | Read the checkout of the head commit. |
run_command, write_file | Run a command or write a file in the sandbox. |
search_items | Search the titles of the issues and pull requests of the repository. |
comment, review | Post a comment, or a review that only comments, as the TanStack Source bot. |
label, close | Label or close the issue or pull request of the run. |
record_verdict | Record a verdict: one short word with lowercase letters, digits and dashes. |
push_fix, merge_base, open_pr | Change a branch. Only with permissions: { contents: 'write' }. |
Your agent can also have its own tools and MCP servers. Their code runs in the sandbox.
The sandbox
- The forge runs each run of an agent in its own job container, with the head commit checked out.
- The container has no key and no token. A secret is a placeholder that starts with
tss_ph_, in an environment variable with the name of the secret. - The agent reaches the forge, and the hosts in
egresson port 443. Nothing else. - Only the agent's own process can call the forge as the agent. A process that it starts, or a command of
run_command, cannot. - Each run uses CI container time. On the items of a person without write access, it counts toward that person's daily limit.
The bundle
The forge bundles each factory file with esbuild. The file can import:
@tanstack-source/ciand@tanstack-source/ci/agent@tanstack/ai,@tanstack/ai-mcpand the TanStack AI adapterszod- Its own files, by a relative path
- For
.source/factory.ts: any file of the repository, by a relative path, and the packages of the repository. See below.
The bundle of the repository file
The forge bundles .source/factory.ts in a checkout of the tip of the default branch. When the root has a package.json and one of these lockfiles, the forge installs the packages first:
| Lockfile | Install |
|---|---|
package-lock.json | npm ci --ignore-scripts |
pnpm-lock.yaml | pnpm install --frozen-lockfile --ignore-scripts |
yarn.lock | Yarn 1: yarn install --frozen-lockfile --ignore-scripts. Yarn 2 and later: yarn install --immutable, with no scripts and a node_modules folder. |
bun.lock, bun.lockb | bun install --frozen-lockfile --ignore-scripts |
- The install runs no package scripts.
- The install of a workspace installs all of its packages, so the file can import the packages of the workspace.
- The install reads packages from
registry.npmjs.organdrepo.yarnpkg.com. For a private registry, see A private package registry. - The checkout takes at most 2 minutes, and the install at most 4 minutes.
- The checkout has no Git LFS files.
- The forge keeps the bundle for the next commits. It bundles again only when one of these changes:
- a file that the bundle read;
- the
package.jsonnearest to that file; - the root
package.json,.npmrc,.yarnrc.yml,pnpm-workspace.yaml,bunfig.tomlor lockfile; - the secrets of the install.
A vault file has no checkout. It can import only the packages in the first list, and the other vault files.
A private package registry
The install can read packages from a private registry, such as GitHub Packages:
- Add a CI secret with the token of the registry. Bind the secret to the hosts of the registry, for example
npm.pkg.github.com. See Trust and secrets. - In your
.npmrc, use the secret as an environment variable, for example//npm.pkg.github.com/:_authToken=${NPM_TOKEN}. - In the factory settings, put the name of the secret in Secrets for the package install.
The install gets a placeholder that starts with tss_ph_, not the value. The forge puts the value in place of the placeholder only in the headers of a request to the hosts of the secret. The install can only read packages: it sends nothing.
A package with native code (a .node file) cannot be bundled. An import that the forge cannot find, or a file with an error, stops all custom agents until you fix it. See Fix an error in the file.
Limits
- A factory has 1 to 20 agents. A factory name and an agent name have letters, digits,
_,.and-, up to 64. - A factory file is at most 256 KiB. An unknown key in an agent is an error.
- An agent names at most 32 secrets and 32 egress hosts.
- A run succeeds when the
runof the agent ends with no error. A verdict counts only fromrecord_verdictin a run that succeeded. - A custom agent does not run on content that screening holds, or for a banned author.