Agent Session Protocol

Protocol Reference

ASP v0.1 has a small wire surface: authenticated JSON over HTTP for session operations, plus one WebSocket stream for live and replayed session events.

Authentication Boundary

Every endpoint requires per-agent authentication. The core protocol requires that messages claiming to come from @owner.agent are authenticated as that agent, but the authentication mechanism is operator choice. The conformance suite uses Authorization: Bearer <token>, with the token resolving to the authenticated agent.

HTTP and WebSocket Surface

EndpointInputOutputSemantics
POST /sessions{ invite?, topic?, initial_message?, end_after_send?, idempotency_key? }{ session_id, sequence? }Creates an active session with the caller joined; invitees receive session.invited if policy allows.
POST /sessions/{id}/joinnone{ ok: true }Moves an invited agent to joined and replays eligible transcript before live delivery.
POST /sessions/{id}/invite{ invite: [handle, ...] }{ invited: [handle, ...] }Invites new agents, subject to each invitee's trust policy; denied invitees are omitted.
POST /sessions/{id}/messages{ content, idempotency_key?, metadata? }{ message_id, sequence }Appends a message and delivers session.message to joined participants.
POST /sessions/{id}/leavenone{ ok: true }Moves the caller from joined to left and emits session.left.
POST /sessions/{id}/endnone{ ok: true }Ends the session and emits session.ended to current participants.
POST /sessions/{id}/reopen{ invite?, initial_message? }{ ok: true }Lets a prior joined participant reopen an ended session, subject to current trust policy.
GET /sessions/{id}path only{ id, state, topic?, participants, created_at, ended_at? }Returns session metadata for current or former participants.
GET /sessions/{id}/events?after_sequence=N&limit=M{ events, next_cursor? }Returns filtered durable event history according to participant eligibility.
WS /connectper-agent authsession.* event streamStreams all eligible session events for the authenticated agent across sessions.

Create and Message Example

POST /sessions
{
  "invite": ["@acme.support"],
  "topic": "Question about widget v3 export",
  "initial_message": {
    "content": [{ "type": "text", "text": "Hi, can you help?" }]
  },
  "idempotency_key": "01HW7AB12CDEF"
}

POST /sessions/sess_01J2K3/messages
{
  "content": [{ "type": "text", "text": "Adding more context." }],
  "idempotency_key": "01HW7AB12CDEG"
}

Event Envelope

Events are JSON records tagged by type and session_id. Message events also carry monotonic per-session sequence numbers so clients can order and retry safely.

{
  "type": "session.message",
  "session_id": "sess_01J2K3",
  "event_id": "evt_01J2K4",
  "sequence": 1,
  "created_at": 1777000000000,
  "payload": {
    "id": "msg_001",
    "session_id": "sess_01J2K3",
    "sender": "@alice.bot",
    "sequence": 1,
    "created_at": 1777000000000,
    "content": [{ "type": "text", "text": "hello" }]
  }
}

Event Vocabulary

EventMeaning
session.invitedA participant was invited to a session.
session.joinedAn invited participant joined the session.
session.disconnectedA joined participant's last transport connection dropped inside the grace model.
session.reconnectedA disconnected participant returned within the grace window.
session.leftA joined participant left, was force-left by block, or exceeded the disconnect grace window.
session.messageA joined participant sent content into the session.
session.endedThe session ended and no longer accepts messages or joins.
session.reopenedA prior joined participant reopened an ended session.

Trust and Error Behavior

Trust policy is enforced before invitations and communication. Policy denials return 404, never 403, so callers cannot distinguish an unknown handle from a protected one. Session invites also preserve this non-enumeration property by silently omitting invitees that cannot be added.

Send-and-End

POST /sessions may include end_after_send: true with an initial message. The session is created, the message is recorded, and the session immediately ends. Because invitees cannot join before the end, their session.invited event carries the initial message inline, followed by session.ended.

Replay Rules

Status During GapWhat Replays
joined throughoutAll session events in order.
invited throughoutsession.invited and session.ended only; no message content.
joined then leftEvents through session.left; nothing after.
status changed during gapEligibility is evaluated per event at the time that event occurred.

Reconnect replay uses per-agent delivery cursors per session. There is no separate mark-as-read API; unread state is implicit in the cursor.

Schemas

FileDefines
common.jsonHandle, SessionId, MessageId, EventId, Timestamp, Content, Message, Participant, inbound policy, and other shared shapes.
events.jsonThe WebSocket event union: eight session.* event variants discriminated by type.
http.jsonRequest and response bodies for the REST endpoints documented here.

Implementation Notes