Outside agents — other AI agents talking to a member's assistant
A member's private assistant can work with AI agents outside Witbitz — Claude Code, Grok, a booking agent, a colleague's assistant — in both directions:
| Direction | How | The member's control |
|---|---|---|
| An agent writes to the assistant | The agent sends a message to the assistant's door, over A2A or MCP, with a token the member gave it. | The assistant drafts the answer; the member approves it before it goes back (unless that agent is set to 'auto'). |
| The assistant gives an agent a job | The assistant calls the agent's trigger — a job agent is a connection — and the agent reports back through the door. | Every job is a proposal the member approves. |
Both run through the standing Sentinel, the attested enclave that holds connections. Outside agents reach a member's private lane (a private assistant inside a Space), never the shared room.
Status: Production. The A2A door has been live since 2026-10-03; the MCP door and job agents serve Claude Code and Grok today. In the SDK,
lane.a2a.mcpUrland job-agent connections arrive in 3.5.0, and marking a job agent's peer (addPeer(name, { job: true })) in 3.6.0.
Open the door to an agent
const wb = new Witbitz({ session, a2a: saved }) // persist wb.a2a.state — it holds the lanes' inbox keys
wb.a2a.onState = (s) => save(s)
const lane = await space.privateLane({ admission: { emails: [me] } })
await lane.a2a.enable({ name: 'Dana’s assistant' })
const { token, cardUrl, mcpUrl } = await lane.a2a.addPeer('Claude Code') // the token is shown onceGive the agent its token and one of the two addresses — the same inbox speaks both protocols:
- MCP — for agents that take a custom MCP server (Claude Code, Grok, Cursor, Claude):
mcpUrlwith the headerAuthorization: Bearer <token>. For Claude Code:claude mcp add --transport http witbitz <mcpUrl> --header "Authorization: Bearer <token>". - A2A — for agents that speak the open A2A protocol: the Agent
Card at
cardUrl, with the token as a bearer.
One token per agent. lane.a2a.removePeer(id) revokes it on both doors at once and drops its waiting messages;
lane.a2a.disable() closes the lane's door; wb.a2a.revoke() turns it off everywhere.
What the agent sees
Over MCP, two tools:
| Tool | What it does |
|---|---|
message_member(text, task_id?) |
Sends a message, a question or a finished result into the member's private lane (up to 8,000 characters). Pass task_id to continue a conversation. Answers with a task_id. |
get_reply(task_id) |
The state — waiting, read, question, answered, declined or expired — and the member's reply once there is one. |
Over A2A, a standard v1.0 JSON-RPC endpoint: SendMessage, GetTask, CancelTask (the v0.3 names work too).
Answers can take hours: a message waits until one of the member's devices collects it. An unanswered one expires after 7 days. Text only — a file is refused.
How a message is answered
lane.on('a2a', ({ peer, text, draft, approve, askBack, decline }) => showForApproval(peer, text, draft))
await lane.a2a.collect() // bring waiting messages into the lane- The message lands in the lane as the agent's words, marked as coming from that agent. The assistant is told to treat it as information, never as instructions.
- The assistant drafts an answer — its ordinary reply in the lane.
- The member decides. With
reply: 'ask'(the default) nothing goes back until the member callsapprove(text?),askBack(question)ordecline().addPeer(name, { reply: 'auto' }), orsetReply(id, 'auto')later, lets the assistant answer that agent on its own. - The agent reads it with
get_reply(MCP) orGetTask(A2A).
Give an agent a job
An agent that is started by a web address — a Claude Code routine's trigger, a Grok routine's webhook — is a connection whose credential the Sentinel keeps. Attach it as a job agent and grant it to the lane:
const claude = await wb.connections.attach({
label: 'Claude Code',
host: 'https://api.anthropic.com/v1/claude_code/routines/trig_…/fire', // the whole trigger address
secret: 'sk-ant-oat01-…', // sent as a Bearer header
webhook: true, // one path, POST only
job: { field: 'text', headers: { 'anthropic-beta': 'experimental-cc-routine-2026-04-01', 'anthropic-version': '2023-06-01' } },
})
await lane.connections.grant(claude)- The assistant proposes; the member approves. Asked to hand work to the agent, the assistant proposes a
connection_call; once a member approves, the Sentinel POSTs the job to that one path, with the fixed headers and the key — which neither the page nor the model ever sees. - Every job tells the agent to report back. The runtime adds a closing line to the job: send the full result, or a
question, with the
message_membertool. So the agent also needs the lane's door — add it as a peer withjob: true(lane.a2a.addPeer('Claude Code', { job: true })) and give its routine themcpUrland token. - The result is a report for the member, not a message to answer. The agent's run has ended and nothing reads a
reply, so the assistant tells the member what came back and never writes back to the agent. If more is needed — a
question to answer, a correction, a next step — it proposes a new job with
connection_call, which the member approves like the first. A peer added withoutjob: trueis answered the way above.
job.field is the field of the request body the job goes in (text for Claude Code); job.headers are fixed headers
every call carries — a credential header can never be named there. A webhook whose secret starts with whsec_ is
signed instead of sent as a bearer, and needs no webhook: true.
Security
- TLS ends inside the attested enclave. A message is sealed there to the lane's inbox key; only the member's devices can open it. Witbitz stores a hash of each token, never the token.
- An outside agent's words are information, not instructions — to the assistant and to the member's approval.
- Grants only to a gated lane. A connection, a job agent included, is granted only where every turn needs the member's sign-in.
- The member can cut one agent off without touching the others.
Read next
- Connections: how the Sentinel keeps and spends credentials.
- The SDK — outside agents over A2A and private lanes.
- Proposals, end to end: the approval every job goes through.
Machine-readable source: outside-agents.md · Generated 2026-10-27T07:05:42Z · build f301388c · every doc in one fetch: llms-full.txt (HTML)