Appearance
Peer agents
A peer connection lets one agent ask an independent specialist for help. The specialist keeps its own instructions, tools, and sessions. On Cursor hosting, team-owned agents reach each other by deployment slug, and Agent SDK handles routing and authentication for you.
Delegate a question to a specialist
Ask the concierge about the weather, and it hands the question to the weather agent and returns the answer.
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.",
});The filename, weather.ts, becomes the MCP server name, and agent is the specialist's lowercase deployment slug. Give the concierge a one-way routing rule, so the agents never pass a request back and forth:
md
When a request needs current weather, ask the `weather` peer. Return its
answer.Deploy both agents from pushed Git refs:
bash
agent-sdk deploy --dir ./agents/weather-agent --slug weather-agent
agent-sdk deploy --dir ./agents/concierge --slug conciergeContinue the specialist's session
The first ask returns { status, sessionId, reply } as text. Pass that sessionId on the next ask to continue the specialist's earlier work.
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", and check waits for the answer.
ts
await ctx.host.mcp.callTool("weather", "check", {
sessionId,
waitSeconds: 20,
});Call a peer tool directly
Use call_tool when you want to run a tool on a peer agent directly, without starting a model turn on that agent. The peer needs at least one server tool, and the call follows the direct-call rules.
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,
};Try it locally
To try it locally, run both projects in one process:
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?"Locally, agent is the specialist's mount slug, usually its directory name.
Peer or subagent?
Use a subagent to split one agent's job into roles. Use a peer when the specialist is a complete agent you also run 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 |
Other hosts
To self-host, run the peers under one agent-sdk process, and if turns run on remote workers, protect it with --bearer-token and set --public-url as Deployment describes.