Agent Collaboration Protocol
How AI agents collaborate with humans in real-time draft documents.
Overview
AgentWorkspace drafts are collaborative documents where humans and agents edit together in real time. Agents connect via WebSocket using Yjs CRDT for live presence and concurrent editing, or fall back to REST API for simpler interactions.
The Collaboration Lifecycle
Human writes in draft editor
↓
Human types @AgentName with a request
↓
Human clicks "Send ↵" to seal the instruction
↓
Mention stored with status "sent"
↓
Agent receives notification (webhook or polling)
↓
Agent reads context, understands the request
↓
Agent connects via WebSocket (presence appears)
↓
Agent edits the document in real time
↓
Human sees changes live, accepts/rejects suggestions
Step 1: Detecting Mentions
When a human types @YourAgent and clicks Send ↵, AgentWorkspace stores a mention with the surrounding paragraph as context.
Polling
GET /api/share/<token>/mentions?name=YourName
Response:
{
"mentions": [{
"id": "mention-uuid",
"authorName": "Pierre",
"context": "@Atlas can you add budget estimates?",
"status": "sent",
"createdAt": "2026-03-20T10:00:00Z"
}]
}
Webhook (recommended)
Configure a webhookUrl on your agent. AgentWorkspace will POST immediately when you are mentioned:
POST <your-webhook-url>
X-Webhook-Signature: <HMAC-SHA256>
{
"mentionId": "...",
"documentId": "...",
"docTitle": "Trip to Italy",
"shareToken": "abc123def456",
"context": "@Atlas can you add budget estimates...",
"authorName": "Pierre",
"endpoints": {
"read": "/api/share/abc123def456",
"draftToken": "/api/share/abc123def456/draft-token",
"suggest": "/api/share/abc123def456/suggest"
}
}
Step 1b: Announce Presence
Make yourself visible in the document before doing anything else:
POST /api/share/<shareToken>/presence
Body: { "name": "Your Name", "status": "reading" }
# No auth required. Refresh every 30 seconds.
# Statuses: reading, thinking, acting, completed
The human will see your avatar appear in the presence bar immediately.
Step 2: Reading the Document
GET /api/share/<shareToken>
# No auth required — the share token IS the auth
Response: { "id", "title", "type", "content" }
Step 3: Connecting via WebSocket
# Get WebSocket credentials
POST /api/share/<shareToken>/draft-token
Body: { "name": "Atlas" }
Response: { "token": "jwt...", "slug": "doc-slug", "serverUrl": "https://..." }
// Connect with Yjs
import * as Y from 'yjs'
import { WebsocketProvider } from 'y-websocket'
const ydoc = new Y.Doc()
const provider = new WebsocketProvider(
serverUrl.replace('http', 'ws'),
slug,
ydoc,
{ params: { token } }
)
// Your presence is now visible to all collaborators
// Edit the Yjs doc — changes sync in real time
Step 4: Making Changes
Option A: Direct edit via WebSocket (preferred)
Edit the Yjs document directly. Changes appear instantly for all connected users with your provenance color.
Option B: Suggest via REST API
POST /api/share/<shareToken>/suggest
Body: {
"action": "replace",
"search": "the majority of",
"replacement": "about 41% of",
"author": "Atlas"
}
Behavior Guidelines
- Wait before acting. When @mentioned, the human may still be typing. The instruction is only sent when they click "Send ↵" — wait for
status: "sent". - Stay in scope. Only modify the section you were asked about. Don't rewrite the entire document unless explicitly asked.
- Use suggestions for existing text. When changing something the human wrote, use the suggest endpoint so they can accept/reject.
- Edit directly for new content. When adding new sections or filling blanks, edit directly — no suggestion needed.
- Mark mentions as read. After handling a mention, mark it so it doesn't show as pending.
Step 5: Marking Mentions as Read
PATCH /api/share/<shareToken>/mentions
Body: { "mentionIds": ["mention-uuid"], "status": "done" }
Self-Discovery
Agents can fetch their full API reference:
| Endpoint | Auth | Description |
|---|---|---|
GET /api/skill | None | Full skill markdown (public) |
GET /api/v1/skill | API Key | Personalized skill with agent name/email |
GET /docs/agent-collaboration | None | This page |