# Peer agents

A peer connection lets one agent ask an independent specialist for help.
On Cursor-managed hosting, team-owned agents reach peers by deployment
slug. Deploy both agents and Agent SDK handles routing and authentication; you
don't configure a URL, header, or secret. The specialist keeps its own
instructions, tools, and session while the caller decides when to delegate
and returns the answer to the user.

## Delegate a question to a specialist

Ask the concierge about the weather and it hands the question to the
specialist. The weather agent answers in its own context, then the
concierge returns that answer to you.

```ts
// bot/mcp-connections/weather.ts
import { defineConnection } from "@grok/agent-sdk/connections";

export default defineConnection({
  agent: "weather-agent",
  description: "Delegate weather questions to the weather specialist.",
});
```

Give the concierge a narrow routing rule:

```md
When a request needs current weather, ask the `weather` peer. Return its
answer.
```

Deploy the specialist and caller from pushed Git refs:

```bash
agent-sdk deploy --dir ./agents/weather-agent --slug weather-agent
agent-sdk deploy --dir ./agents/concierge --slug concierge
```

The connection filename, `weather.ts`, becomes the MCP server name the
concierge calls. Set `agent` to the specialist's lowercase deployment slug.

## Continue the specialist's session

Ask a follow-up about the same forecast and the specialist picks up
where it left off, with its own instructions and tool history still in
place. The first `ask` returns `{ status, sessionId, reply }` as text on
the `callTool` result. Parse `sessionId` and pass it on the next `ask`
so the peer remembers its earlier work instead of starting fresh.

```ts
const first = await ctx.host.mcp.callTool("weather", "ask", {
  message: "What's the weather in Paris right now?",
});
const firstText = first.content.find((part) => part.type === "text");
if (firstText?.text === undefined) {
  throw new Error("weather ask returned no text payload");
}
const { sessionId } = JSON.parse(firstText.text) as { sessionId: string };

await ctx.host.mcp.callTool("weather", "ask", {
  message: "How does that compare with tomorrow?",
  sessionId,
});
```

If the specialist is still working, `ask` returns `status: "running"`
with the session ID, and you can do other work before calling `check`.

```ts
await ctx.host.mcp.callTool("weather", "check", {
  sessionId,
  waitSeconds: 20,
});
```

The peer owns this session, so follow-ups continue the specialist's
context.

## Call a deterministic peer tool

You need a forecast for Paris, and the weather agent already has
`get_forecast`. Host code calls that tool in the specialist's workspace
and the forecast comes back to the concierge, with no second model turn.

```ts
const result = await ctx.host.mcp.callTool("weather", "call_tool", {
  toolName: "get_forecast",
  input: { city: "Paris" },
});
const part = result.content.find((item) => item.type === "text");
if (part?.text === undefined) {
  return { ok: false, forecast: null };
}
const payload = JSON.parse(part.text) as {
  isError?: boolean;
  result?: unknown;
};

return {
  ok: result.isError !== true && payload.isError !== true,
  forecast: payload.result ?? null,
};
```

`call_tool` appears only when the peer declares at least one
deterministic server tool.

## Try it locally

Run both projects under one process to try the same connection locally:

```bash
agent-sdk dev ./agents
agent-sdk chat --url http://127.0.0.1:3000/concierge \
  --message "What's the weather in Paris right now?"
```

In a local multi-agent serve, `agent` is the specialist's mount slug,
normally its directory name.

## Peer or subagent?

Use a [subagent](/docs/reference/subagents.md) to split one agent's job
into roles that share its project. Use a peer when the specialist is a
complete agent you would also run, inspect, or expose on its own.

| | Subagent | Peer |
| --- | --- | --- |
| Context | Child role inside one agent | Independent agent and session |
| Tools and connections | Inherits the parent project | Owns its project surface |
| Reachability | Parent only | Local co-hosted agents, or declared deployments on the same team |

## Affinity

Peer sessions appear in the specialist's playground. Only the calling
deployment can continue a hosted peer session.

## Practices

- Give each caller a one-way routing rule, and don't configure reciprocal
  routes for the same request.

- Prefer `ask` when the specialist should reason. Use `call_tool` when
  host code already knows which server tool to run.

## Other hosts

For self-hosting, run peers under one `agent-sdk` process. If turns run on remote
workers, protect the process with `--bearer-token` and set its external URL
with `--public-url`. Hosts that run one agent per process can supply
`--peers-url`; Cursor-managed hosting configures it automatically. See
[Deployment](/docs/deployment.md) for the secure hosting setup.

## Related

- [MCP connections](/docs/reference/connections.md#peer-mcp-connection):
  peer configuration and connection naming
- [MCP endpoint](/docs/reference/http-api.md#mcp-endpoint): exact `ask`,
  `check`, and `call_tool` schemas
- [Subagents](/docs/reference/subagents.md): specialists inside one agent
- [Deployment](/docs/deployment.md): secure shared-host setup
