---
title: Tool surface
description: Every tool Foreman can reach, where it is mounted, and the gate in front of it, covering root tools, the GitHub extension, Linear, and per-station tools.
type: reference
summary: Full reference for root tools, the GitHub extension, the Linear connection, per-station tools, and skills.
related:
  - /docs/trust-model
  - /docs/stations
  - /docs/memory
---

# Tool surface



Every tool Foreman can reach is mounted in one of four places: root tools in `agent/tools/`, the GitHub extension in `agent/extensions/github.ts`, the Linear MCP connection in `agent/connections/linear.ts`, and station-local tools inside each station's directory.

Terms like parks, denied, and unattended are defined in the [glossary](/docs/glossary). The [trust model](/docs/trust-model) explains how runs earn trust and what each policy returns.

## Root tools

The orchestrator's own tools live in `agent/tools/`, one file per tool. In eve the filename is the identity, so `agent/tools/read_factory_brain.ts` is the tool `read_factory_brain`. Five handle [memory](/docs/memory); the sixth disables a framework built-in.

| Tool                     | Purpose                                                                                                       | Gate                               |
| ------------------------ | ------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| `get_user_preferences`   | Load the calling user's standing preferences. The key derives from the resolved principal, never model input. | none                               |
| `save_user_preferences`  | Overwrite the user's preferences document. Read, merge, save; 20,000 character cap.                           | none                               |
| `clear_user_preferences` | Permanently delete the user's preferences.                                                                    | `always()`, parks for every caller |
| `read_factory_brain`     | Load the shared per-repository brain. Returns an empty document when nothing is recorded.                     | none, open to every run            |
| `update_factory_brain`   | Overwrite the whole brain document. 40,000 character cap.                                                     | `factoryBrainPolicy`               |
| `agent`                  | Disabled.                                                                                                     | n/a                                |

eve ships a built-in `agent` tool that runs a fresh copy of the root agent. That would let the orchestrator delegate work to an undifferentiated clone of itself and bypass the four stations, so `agent/tools/agent.ts` exports `disableTool()` and all delegation goes through the declared subagents instead.

The two gated tools show the two kinds of gate in the template. `clear_user_preferences` uses `always()` because deletion is irreversible no matter who asks. `update_factory_brain` uses a trust policy because the answer depends on the caller: an unattended run driven by an issue body must never write the shared context every future run reads.

## The GitHub extension

`agent/extensions/github.ts` mounts `@github-tools/eve-extension`. The filename is the namespace, so tools appear to the model as `github__<name>`. Credentials are brokered by Vercel Connect through `GITHUB_CONNECTOR`, resolved per call and never exposed to the model.

Two configuration choices carry most of the security weight. `include` is an explicit allowlist with no preset, so a tool the extension ships but the list omits does not exist for the model. And `context: factoryRepo` fills `owner` and `repo` on every call from `FACTORY_REPO`, so the model never picks the repository. Foreman cannot be talked into operating on a different repository because there is no parameter to redirect.

The allowlist holds 31 tools: 19 reads that run ungated for every caller, and 12 writes mapped to policies.

### Reads

| Category      | Tools                                                                                         |
| ------------- | --------------------------------------------------------------------------------------------- |
| Repository    | `getRepository`, `getRepositoryTree`, `getFileContent`, `searchCode`, `listBranches`          |
| Commits       | `listCommits`, `getCommit`, `compareCommits`                                                  |
| Issues        | `searchIssues`, `listIssues`, `getIssueContext`, `listIssueComments`, `listLabels`            |
| Pull requests | `listPullRequests`, `getPullRequestContext`, `listPullRequestFiles`, `listPullRequestReviews` |
| CI            | `listCheckRuns`, `getCiFailureContext`                                                        |

### Writes and their policies

| Tool                                                                                          | Policy                                                                                              |
| --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `createIssue`, `addAssignees`, `removeAssignees`, `requestReviewers`, `addPullRequestComment` | `writePolicy`                                                                                       |
| `addIssueComment`                                                                             | `commentPolicy`: unattended runs may comment only on their own stamped intake issue                 |
| `addLabels`, `removeLabel`                                                                    | `labelPolicy`: allowed even unattended                                                              |
| `closeIssue`                                                                                  | `closeIssuePolicy`: runs for every caller, since closing is reversible triage                       |
| `updateIssue`                                                                                 | `updateIssuePolicy`: a `state` change routes to the close policy, anything else to the write policy |
| `createPullRequest`                                                                           | `createPullRequestPolicy`: `draft: true` runs, a non-draft routes to the ship policy                |
| `updatePullRequest`                                                                           | `shipPolicy`: parks for a person no matter who asks, denied unattended                              |

<Callout type="info" title="Fail-closed by default">
  A write tool added to `include` without a `requireApproval` entry keeps the SDK's approval-by-default, so a missed mapping tightens the gate rather than opening it.
</Callout>

### What is deliberately absent

The allowlist omits whole categories.

Merge tools are absent because a draft pull request is the factory's ceiling and a person marks ready and merges in the GitHub UI. There is no merge tool to misuse, gate, or approve.

Repository administration is absent because the factory changes code, not settings. Gists are absent because they return 403 over Connect installation tokens anyway. Releases and CI mutation are absent because the factory reads CI results but cannot re-run, cancel, or edit workflows.

If you want merge behind an approval card, [customizing](/docs/customization) shows the one-line change.

## The Linear connection

`agent/connections/linear.ts` registers the Linear MCP server at `https://mcp.linear.app/mcp`, giving the orchestrator Linear's own tools for issues, projects, cycles, and comments. Auth is app-scoped through Vercel Connect and shared with the Linear channel.

The connection carries one connection-wide approval predicate: writes are denied for unattended runs and ungated for attended sessions. Every Linear Agent Session is stamped trusted at dispatch because workspace membership is the gate, so Linear writes run freely for Linear-originated work and are refused when the factory is running on its own.

## Per-station tools

Stations inherit nothing from the root, so anything a station can do is declared in its own directory. That keeps each station's blast radius readable at a glance.

| Station     | Authored tools                   | Sandbox                 |
| ----------- | -------------------------------- | ----------------------- |
| Classifier  | none                             | default, empty          |
| Analyst     | none                             | own, with repo checkout |
| Implementer | `checkout_branch`, `push_branch` | own, with repo checkout |
| Reviewer    | `checkout_branch`                | own, with repo checkout |
| Researcher  | none                             | default, empty          |

Authored tools are the ones written specifically for that station, in its own `tools/` directory. On top of those, every station gets eve's default tools: shell and file tools against its own sandbox, plus `web_fetch`, `web_search` where the provider supports it, and `todo`.

Anything a station leaves unspecified falls back to an eve default rather than to nothing, which matters in two places. Every eve agent gets a sandbox whether or not it asks for one, so the Classifier and Researcher still have a working `/workspace`; theirs is just empty. And four built-ins are missing: `load_skill` and `connection_search` show up only for agents with skills or connections, `ask_question` needs a session that can pause for a person, and the root-only `agent` tool never reaches a station.

So what actually limits a station is its empty or full sandbox and what its instructions permit, not a short tool list. The [stations reference](/docs/stations) covers each one in detail.

Every station declares an `outputSchema`, which puts it in task mode: structured output, and no ability to stop for approval or input. That is why no station holds an approval-gated tool. A tool that returned `user-approval` inside a task-mode child would strand the run, so station side effects are inert by construction instead.

`push_branch` runs `validateBranch` on its input, which refuses `main`, `master`, and anything that is not a plain branch name, so the tool cannot change the default branch or merge. The push targets the literal repository URL rather than the model-writable `origin` remote, and the installation token is injected at the sandbox firewall and dropped in a `finally`, so the credential never enters the sandbox.

`checkout_branch` exists in two places for two reasons. The Implementer uses it to fetch an existing branch for a revision run. The Reviewer uses it to fetch the branch under review into its own checkout, so the review sees only what was pushed, never the Implementer's working state.

## Skills

Skills are load-on-demand instruction packages under `agent/skills/<name>/SKILL.md`. Each one's `description` frontmatter is the routing hint that tells the orchestrator when to load it. Skills are per-agent, so stations never see them, and the orchestrator folds anything a station needs into the delegation message.

| Skill                    | Covers                                                                                                                | Loaded when                                                                              |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `writing-quality`        | Guardrails for prose meant for humans: pull request descriptions, issue comments, review reports, Linear replies      | Writing or revising human-facing content. Not needed for code, queries, or tool plumbing |
| `triaging-issues`        | Dedupe, label with the repository's existing vocabulary, decide whether to ask or proceed, request reproductions well | A work item arrives from a GitHub issue or mention                                       |
| `github-linear-bridging` | Check for an existing bridged issue, choose the team, cross-link both directions                                      | The item spans both trackers                                                             |

## Next steps

<Cards>
  <Card href="/docs/trust-model" title="Trust model" description="The policies these gates reference, and why unattended runs are denied." />

  <Card href="/docs/stations" title="Stations reference" description="What each station does with the tools it holds." />

  <Card href="/docs/customization" title="Customizing" description="Add tools, remap policies, or give a station new capabilities." />
</Cards>


---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)