Examples

Example: a manager agent with scoped sub-agents

A broadly-capable GitHub manager agent that delegates to specialist eve sub-agents, each scoped to one preset (code-review, issue-triage, release-manager), instead of one agent holding every tool.

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:

agent/instructions.md
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
agent/agent.ts
import { defineAgent } from 'eve'

export default defineAgent({
  model: 'anthropic/claude-sonnet-5',
})

The reviewer sub-agent

agent/subagents/reviewer/instructions.md
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.
agent/subagents/reviewer/agent.ts
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',
})
agent/subagents/reviewer/extensions/github.ts
import githubExtension from '@github-tools/eve-extension'

export default githubExtension({
  connector: 'github/my-connector',
  preset: 'code-review',
})

The triager sub-agent

agent/subagents/triager/instructions.md
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.
agent/subagents/triager/agent.ts
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',
})
agent/subagents/triager/extensions/github.ts
import githubExtension from '@github-tools/eve-extension'

export default githubExtension({
  connector: 'github/my-connector',
  preset: 'issue-triage',
  requireApproval: {
    addIssueComment: false,
  },
})

The releaser sub-agent

agent/subagents/releaser/instructions.md
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.
agent/subagents/releaser/agent.ts
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',
})
agent/subagents/releaser/extensions/github.ts
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
.env
# 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

Terminal
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.

A declared subagent inherits nothing from the root except the framework defaults. Each 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:

manager-agent.ts
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-audit if the manager should also field vulnerability reports
  • Set outputSchema on 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