Getting Started
This guide walks through a basic client-server interaction using the Agent Host Protocol.
The shape of every message
Before walking through the handshake, note the one structural rule that runs through every example below: every command's and every notification's params carries a top-level channel: URI. Channel-scoped messages set it to the target channel (e.g. ahp-session:/<uuid>); connection-level commands set it to 'ahp-root://'. Servers, clients, and intermediate proxies dispatch every message by (method, params.channel). See Channels & Subscriptions for the full model.
Connection Handshake
Every AHP session starts with a JSON-RPC handshake over the transport (WebSocket, MessagePort, etc.):
1. Client → Server: initialize(channel: 'ahp-root://', protocolVersions[], clientId, initialSubscriptions?)
2. Server → Client: { protocolVersion, serverSeq, snapshots[], defaultDirectory? }The initialSubscriptions field allows the client to subscribe to root state and any previously-open sessions in the same round-trip as the handshake. The server returns snapshots for each in the response. The optional defaultDirectory field gives clients a sensible starting point for remote filesystem browsing.
Subscribing to State
After connecting, clients subscribe to URI-identified channels. Root state is always available at ahp-root://:
// Client → Server (request)
{
"jsonrpc": "2.0",
"id": 1,
"method": "subscribe",
"params": { "channel": "ahp-root://" }
}
// Server → Client (response)
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"snapshot": {
"resource": "ahp-root://",
"state": {
"agents": [
{
"provider": "copilot",
"displayName": "Copilot",
"description": "GitHub Copilot agent",
"models": [
{ "id": "gpt-4o", "name": "GPT-4o", "provider": "copilot" }
]
}
]
},
"fromSeq": 5
}
}
}After subscribing, the client receives all subsequent actions scoped to that channel via server-pushed notifications.
Creating a Session
Session creation uses an imperative RPC command:
// 1. Client picks a session URI
// 2. Client sends createSession command
{
"jsonrpc": "2.0",
"id": 2,
"method": "createSession",
"params": {
"channel": "ahp-session:/<uuid>",
"provider": "copilot",
"model": "gpt-4o"
}
}
// 3. Client subscribes to the session URI
{
"jsonrpc": "2.0",
"id": 3,
"method": "subscribe",
"params": { "channel": "ahp-session:/<uuid>" }
}The initial snapshot has lifecycle: 'creating'. The server asynchronously initializes the agent backend, then dispatches either a session/ready or session/creationFailed action.
Sending a Message
To start a turn, the client dispatches a session/turnStarted action. This is a write-ahead action — the client applies it optimistically to its local state:
// Client → Server (notification, fire-and-forget)
{
"jsonrpc": "2.0",
"method": "dispatchAction",
"params": {
"channel": "ahp-session:/<uuid>",
"clientSeq": 1,
"action": {
"type": "session/turnStarted",
"turnId": "turn-1",
"message": { "text": "Explain this code", "origin": { "kind": "user" } }
}
}
}The server begins agent processing and streams back actions:
// Server → Client: streaming text delta
{ "method": "action", "params": {
"channel": "ahp-session:/<uuid>",
"action": { "type": "session/delta", "turnId": "turn-1", "partId": "p1", "content": "This code " },
"serverSeq": 6
}}
// Server → Client: more streaming text
{ "method": "action", "params": {
"channel": "ahp-session:/<uuid>",
"action": { "type": "session/delta", "turnId": "turn-1", "partId": "p1", "content": "defines a function..." },
"serverSeq": 7
}}
// Server → Client: turn complete
{ "method": "action", "params": {
"channel": "ahp-session:/<uuid>",
"action": { "type": "session/turnComplete", "turnId": "turn-1" },
"serverSeq": 8
}}Handling Tool Calls
When the agent invokes a tool, the server emits a sequence of actions modelling the tool call's lifecycle (see State Model — Tool Call Lifecycle for the full state machine):
session/toolCallStart— a new tool call begins.session/toolCallDelta— partial parameters stream in.session/toolCallReady— parameters complete. If the tool requires user confirmation, the call transitions topending-confirmation; otherwise it goes directly torunning.session/toolCallComplete— tool execution finished.
The client resolves a pending-confirmation tool call by dispatching session/toolCallConfirmed:
// Client → Server: approve the tool call
{
"jsonrpc": "2.0",
"method": "dispatchAction",
"params": {
"channel": "ahp-session:/<uuid>",
"clientSeq": 2,
"action": {
"type": "session/toolCallConfirmed",
"turnId": "turn-1",
"toolCallId": "tc-1",
"approved": true,
"confirmed": "user"
}
}
}To deny, dispatch the same action with approved: false and a reason ("denied" or "skipped").
Next Steps
- State Model — Full state tree structure.
- Messages Reference — Index of every JSON-RPC method, linked to the channel that documents it.