Example: a manager agent with scoped sub-agents
Build a manager agent with scoped sub-agents
Instead of one agent holding all 53 tools, this manager holds none. It reads the request, picks the right specialist, and calls it. Each specialist is a normal @github-tools/eve-extension mount scoped to a single preset, isolated in its own declared subagent directory with its own tools, instructions, and approval policy.
Why declared subagents
eve ships two ways to delegate: the built-in agent tool (spins up a fresh copy of the same agent) and declared subagents (specialists with their own directory, tools, and prompt). A manager that routes between a reviewer, a triager, and a release manager needs the second kind, three different roles with three different tool surfaces, not three copies of the same agent.
A declared subagent under agent/subagents/<id>/ is compiled as its own agent root: its own instructions.md, its own extensions/, nothing inherited from the parent except the root-only agent and Workflow tools, which subagents never receive anyway. eve exposes each declared subagent to the parent as a tool with the shape { message: string, outputSchema?: object }, named after its directory, no namespace prefix. That is the mechanism this example uses: reviewer, triager, and releaser become three plain tool calls the manager's model can make.
File tree
agent/
├── agent.ts # manager: no GitHub extension of its own
├── instructions.md # routing logic
└── subagents/
├── reviewer/
│ ├── agent.ts # description required
│ ├── instructions.md
│ └── extensions/
│ └── github.ts # preset: 'code-review'
├── triager/
│ ├── agent.ts
│ ├── instructions.md
│ └── extensions/
│ └── github.ts # preset: 'issue-triage'
└── releaser/
├── agent.ts
├── instructions.md
└── extensions/
└── github.ts # preset: 'release-manager'
The manager
The root agent has no extensions/github.ts of its own. It only knows how to route:
You are the GitHub manager for this repository. You never call GitHub tools directly,
you only have three specialists available as tools: reviewer, triager, and releaser.
Routing rules:
- Pull request review, diffs, or code quality questions: call reviewer
- Issue classification, labeling, or backlog questions: call triager
- Changelogs, release notes, or "what changed since the last release": call releaser
- If a request spans more than one specialist, call each in turn and combine their answers
- Pass each specialist everything it needs in the message, it never sees this conversation
import { defineAgent } from 'eve'
export default defineAgent({
model: 'anthropic/claude-sonnet-5',
})
The reviewer sub-agent
You are a code review specialist. Read the PR description and changed files,
check for bugs and edge cases, and reply with a concise, actionable summary.
Ask before merging or approving anything.
import { defineAgent } from 'eve'
export default defineAgent({
description: 'Reviews pull requests: reads diffs, checks CI status, and drafts review comments.',
model: 'anthropic/claude-sonnet-5',
})
import githubExtension from '@github-tools/eve-extension'
export default githubExtension({
connector: 'github/my-connector',
preset: 'code-review',
})
The triager sub-agent
You are an issue triage specialist. Classify issues as bug, feature, or question,
apply the matching label, and post a short comment with your reasoning.
import { defineAgent } from 'eve'
export default defineAgent({
description: 'Triages GitHub issues: classifies, labels, and comments with a suggested next step.',
model: 'anthropic/claude-sonnet-5',
})
import githubExtension from '@github-tools/eve-extension'
export default githubExtension({
connector: 'github/my-connector',
preset: 'issue-triage',
requireApproval: {
addIssueComment: false,
},
})
The releaser sub-agent
You are a release management specialist. Compare the latest two releases, summarize what
changed, and draft release notes grouped by feature, fix, and other. Confirm the target
before creating anything.
import { defineAgent } from 'eve'
export default defineAgent({
description: 'Prepares releases: summarizes changes since the last tag and drafts release notes.',
model: 'anthropic/claude-sonnet-5',
})
import githubExtension from '@github-tools/eve-extension'
export default githubExtension({
connector: 'github/my-connector',
preset: 'release-manager',
})
Install
pnpm add @github-tools/eve-extension @vercel/connect eve
npm install @github-tools/eve-extension @vercel/connect eve
yarn add @github-tools/eve-extension @vercel/connect eve
bun add @github-tools/eve-extension @vercel/connect eve
# Vercel Connect OIDC token, shared by all three subagent connectors below.
# vercel link && vercel env pull
VERCEL_OIDC_TOKEN=
All three specialists reuse the same github/my-connector connector in this example. Give each one a different connector (or connect.repositories override) if they should see different repositories, see Multi-tenant and repository scoping.
Run it
npx eve dev
Ask the manager "review PR #42 and check if the CHANGELOG needs updating for the next release." It calls reviewer for the PR, releaser for the changelog question, and combines both answers, each specialist working with only the tools and prompt it needs.
extensions/github.ts above is a complete, independent mount: its own connector call, its own preset, its own approval policy. Duplicating those three lines per specialist is the cost of true isolation, see the isolation boundary.Without eve: agent-as-tool with the AI SDK
If the project isn't on eve, the same idea works with the AI SDK by exposing each createGithubAgent as a callable tool() for a manager ToolLoopAgent:
import { createGithubAgent } from '@github-tools/sdk'
import { connectGithubToken } from '@github-tools/sdk/connect'
import { ToolLoopAgent, tool } from 'ai'
import { z } from 'zod'
function specialist(preset: 'code-review' | 'issue-triage' | 'release-manager', description: string) {
const agent = createGithubAgent({
model: 'anthropic/claude-sonnet-4.6',
token: connectGithubToken('github/my-connector', { preset }),
preset,
requireApproval: false,
})
return tool({
description,
inputSchema: z.object({ message: z.string().describe('Everything the specialist needs to complete the task') }),
execute: async ({ message }) => {
const { text } = await agent.generate({ prompt: message })
return text
},
})
}
export const manager = new ToolLoopAgent({
model: 'anthropic/claude-sonnet-4.6',
instructions: 'Route GitHub requests to the right specialist tool: reviewer, triager, or releaser.',
tools: {
reviewer: specialist('code-review', 'Reviews pull requests and drafts review comments.'),
triager: specialist('issue-triage', 'Classifies and labels GitHub issues.'),
releaser: specialist('release-manager', 'Drafts release notes from merged pull requests.'),
},
})
This is a hand-rolled version of the same pattern eve gives you natively: a tool per specialist, its own preset and prompt, no shared state between them. eve's declared subagents add the pieces this snippet leaves out: durable sessions, parallel dispatch, and per-subagent sandboxes, see Subagents in the bundled eve docs.
Go further
- Add a fourth specialist for
security-auditif the manager should also field vulnerability reports - Set
outputSchemaon a subagent call to get structured output back instead of free text, useful when the manager needs to combine multiple specialists' answers programmatically - Read Dynamic workflows if the manager should fan out to multiple specialists in parallel rather than one at a time
Issue triage bot
A durable GitHub bot that triages @mentioned issues, classifies them, and labels them, built with Chat SDK, Vercel Workflow, the issue-triage preset, and Vercel Connect.
Recipes
Short, focused GitHub agent snippets, selective approval, a reusable review agent, read-only exploration, toolpick, and evlog observability.