Skip to content
Source

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

FieldRequiredWhat it is
agentYesA TanStack AI agent: defineAgent({ name, description, run }) from @tanstack/ai. Its description shows on the settings page.
onYesThe events that start it: issue.opened, pull.opened, pull.pushed, label.added.
triggerYesWho starts it. See below.
budgetYesmaxTokens from 1 to 2,000,000. maxCostCents is optional, for a provider that reports a cost.
modelNo{ provider, model }, for ctx.forge.model(). Without it, the agent uses Workers AI.
secretsNoNames of repository CI secrets. See MCP servers and secrets.
egressNoThe https hosts that the agent can reach, such as mcp.linear.app.
permissionsNo{ 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' }, with read, triage, write, maintain or admin
  • { 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:

MemberWhat 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.
itemThe issue or pull request: kind, number, title, author and labels. A pull request also has pull.headRef and pull.headCommit.
agentThe name of the agent in the factory file.
toolsThe 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:

ToolWhat it does
read_file, list_files, search, diffRead the checkout of the head commit.
run_command, write_fileRun a command or write a file in the sandbox.
search_itemsSearch the titles of the issues and pull requests of the repository.
comment, reviewPost a comment, or a review that only comments, as the TanStack Source bot.
label, closeLabel or close the issue or pull request of the run.
record_verdictRecord a verdict: one short word with lowercase letters, digits and dashes.
push_fix, merge_base, open_prChange 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 egress on 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/ci and @tanstack-source/ci/agent
  • @tanstack/ai, @tanstack/ai-mcp and the TanStack AI adapters
  • zod
  • 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:

LockfileInstall
package-lock.jsonnpm ci --ignore-scripts
pnpm-lock.yamlpnpm install --frozen-lockfile --ignore-scripts
yarn.lockYarn 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.lockbbun 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.org and repo.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.json nearest to that file;
    • the root package.json, .npmrc, .yarnrc.yml, pnpm-workspace.yaml, bunfig.toml or 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:

  1. 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.
  2. In your .npmrc, use the secret as an environment variable, for example //npm.pkg.github.com/:_authToken=${NPM_TOKEN}.
  3. 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 run of the agent ends with no error. A verdict counts only from record_verdict in a run that succeeded.
  • A custom agent does not run on content that screening holds, or for a banned author.