Agent Handoff Protocol (AHP) Specification
Version: 1.0.0-rc1 Status: Release Candidate Last Updated: 2026-01-23
Part 1: Protocol Core
1. Abstract
The Agent Handoff Protocol (AHP) defines a standard mechanism for AI agents to autonomously provision, populate, and hand off temporary workspaces to humans without requiring browser-based signup flows.
This protocol enables the "agent builds → human evaluates → human claims" pattern.
2. Terminology
| Term | Definition |
|---|---|
| Sandbox | A temporary, isolated workspace created by an agent |
| Agent | An autonomous software client (LLM, CLI, tool) |
| Human | The end user who may claim ownership |
| Provider | The service implementing this protocol |
| Claim | The act of transferring sandbox ownership to a human account |
| Preview | Read-only access for human evaluation before claim |
| Public Handle | The identifier used in URLs visible to humans |
Normative keywords: MUST, MUST NOT, SHOULD, SHOULD NOT, MAY per RFC 2119.
3. Protocol Goals
- Zero-signup provisioning: Agents can create working infrastructure without human interaction
- Human-in-the-loop for ownership: Humans decide whether to claim after seeing real output
- Clean abandonment: Unclaimed sandboxes disappear without orphaned accounts
- Abuse resistance: Protocol is designed for hostile internet conditions
4. Protocol Non-Goals
- Billing or payment processing
- Long-term data persistence
- Multi-tenant collaboration (within sandbox)
- Production-grade SLAs
5. Sandbox State Machine
┌─────────────┐
│ created │
└──────┬──────┘
│
▼
┌─────────────┐
┌───────│ active │───────┐
│ └──────┬──────┘ │
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ published │ │ expired │ │ deleted │
└──────┬──────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│ claimed │──────► [Real Workspace]
└─────────────┘
Allowed transitions:
created→active(on successful provisioning)active→published(on first content publish)active→expired(on TTL expiration)active→deleted(on explicit delete)published→claimed(on successful claim)published→expired(on TTL expiration)published→deleted(on explicit delete)
Disallowed transitions:
expired→ any statedeleted→ any stateclaimed→ any sandbox state (becomes real workspace)
Part 2: API Specification
6. Discovery
6.1 Well-Known Endpoint
GET /.well-known/agent-access
Response:
{
"ahp_version": "1.0",
"provider": {
"name": "Provider Name",
"docs": "https://..."
},
"sandbox": {
"enabled": true,
"admission": ["proof_of_work"],
"challenge_endpoint": "https://...",
"create_endpoint": "https://...",
"ttl_hours": 48
},
"security": {
"handle_rotation_on_claim": true,
"handle_rotation_on_publish": true,
"adaptive_pow": true
},
"content_types": ["faq"],
"claim": {
"method": "code_plus_pow"
}
}
7. Sandbox Lifecycle
7.1 Admission Challenge
GET /v1/sandboxes/challenge
Response:
{
"challenge": "{random_bytes_hex}",
"difficulty": 20,
"algorithm": "sha256_leading_zeros",
"expires_at": "ISO8601",
"note": "Difficulty is adaptive and may change"
}
7.2 Create Sandbox
POST /v1/sandboxes
Content-Type: application/json
{
"admission": {
"type": "proof_of_work",
"challenge": "...",
"nonce": "..."
},
"metadata": {}
}
Response (201):
{
"id": "{internal_id}",
"public_handle": "{public_handle}",
"status": "active",
"expires_at": "ISO8601",
"agent_token": {
"token": "...",
"expires_at": "ISO8601",
"scopes": ["sandbox:manage", "content:write", "content:publish"]
},
"endpoints": {
"content": "https://...",
"preview": "https://...",
"claim": "https://...",
"delete": "https://..."
}
}
Note: public_handle will change on publish and claim (see §15.1).
7.3 Publish Content
POST /v1/content/{id}/publish
Authorization: Bearer {agent_token}
Response:
{
"id": "...",
"status": "published",
"published_url": "https://{new_public_handle}.provider.net/...",
"previous_handle": "{old_handle}",
"new_handle": "{new_handle}",
"handle_rotated": true
}
The public_handle changes on publish. Previous URLs become invalid.
7.4 Claim Completion
On successful claim:
- Sandbox converts to permanent workspace
- Public handle is rotated (old URLs become invalid)
- All sandbox tokens are invalidated
- All preview sessions are terminated
- All outstanding exchange codes are invalidated
Part 3: Security Considerations
This section is normative. Non-conformant implementations MUST NOT claim AHP compliance.
8. Threat Model
8.1 Assets
| Asset | Description |
|---|---|
| Sandbox resources | Storage, compute, bandwidth, published content |
| Preview admin session | Read-only but privileged UI surface |
| Claim flow | Ownership transfer boundary |
| Provider infrastructure | Internal services, metadata endpoints |
| Provider reputation | Domain trust, SEO standing, abuse listings |
| Human identity | Email addresses, authentication state |
8.2 Trust Boundaries
| Zone | Trust Level | Notes |
|---|---|---|
| Agent runtime | Untrusted | Tokens leak, memory inspected, logs scraped |
| Human browser | Partially trusted | Extensions, prefetchers, scanners present |
| Preview admin UI | Untrusted content | Renders attacker-controlled input |
| Provider backend | Trusted | Enforces all invariants |
| Third-party URLs | Hostile | SSRF, DNS rebinding, timing attacks |
9. Security Invariants
The following invariants MUST hold:
- Sandbox provisioning is a security boundary, not an API convenience.
- No public identifier may grant access unless it has cryptographically sufficient entropy.
- Sandbox content MUST be treated as untrusted and non-executable.
- Preview and claim surfaces MUST be isolated from real administrative sessions.
- Ownership transfer MUST be hardened against brute force, replay, and oracle attacks.
- Abuse prevention MUST assume adversarial automation, not good faith clients.
Failure to uphold any invariant invalidates protocol compliance.
10. Non-Observable Information
The following information MUST NOT be observable by unauthenticated callers through any channel (including error messages, HTTP status codes, response timing, or behavioral differences):
| Information | Attack if Observable |
|---|---|
| Whether a sandbox ID exists | Enumeration |
| Whether a public handle is valid | Enumeration |
| Whether a claim code exists | Oracle attack |
| Whether an exchange code was already used | Oracle attack |
| Whether a sandbox is in active vs expired state | Timing attack |
| Whether content exists at a given path | Enumeration |
| Internal sandbox ID from public handle | Correlation |
Implementation requirements:
- Error responses for "not found," "expired," "invalid," and "already used" MUST be identical in shape, status code, and timing.
- Response times MUST be normalized (e.g., constant-time comparison, artificial delays).
- Rate limiting MUST apply before existence checks.
11. Admission Control
Anonymous sandbox creation creates an account factory. Without admission control, abuse is guaranteed.
11.1 Requirements
Sandbox creation endpoints MUST NOT rely solely on:
- IP-based rate limiting
- Client-provided identifiers
- Unauthenticated bearer tokens
Implementations MUST require at least one of:
- Proof-of-Work (PoW) challenge
- External issuer / agent registration token
- Reputation-based throttling with anomaly detection
Rate limiting alone is not a defense.
11.2 Adaptive Proof-of-Work
Static PoW difficulty values are insufficient under adversarial conditions.
Providers MUST:
- Dynamically adjust PoW difficulty based on observed abuse patterns
- Increase difficulty during attack conditions
- Combine PoW with behavioral throttling
Providers SHOULD:
- Monitor sandbox creation velocity
- Detect anomalous patterns (geographic, temporal, behavioral)
- Implement circuit breakers during abuse spikes
PoW is friction, not identity. It MUST NOT be the only long-term admission control.
12. Identifier and Entropy Requirements
12.1 Public Access Identifiers
Any identifier that gates access to sandbox content, preview content, or unpublished resources MUST:
- Contain ≥128 bits of entropy
- Be uncorrelated with internal identifiers
- Be non-sequential and non-derivable
- Not leak via logs, analytics, or error messages
12.2 Internal Identifiers
Internal identifiers (sandbox IDs, workspace IDs):
- MUST NOT appear in public URLs
- MUST NOT be derivable from public identifiers
- MUST NOT be exposed in error messages or timing side channels
13. Sandbox Content Restrictions
13.1 No Anonymous Hosting
Sandboxes MUST NOT function as general-purpose hosting.
Requirements:
- Sandbox-origin responses MUST be limited to provider-defined content routes.
- Arbitrary path routing MUST NOT be supported.
- Sandbox content MUST NOT be able to serve arbitrary HTML, JS, or HTTP headers.
- Sandbox content MUST NOT be able to set cookies on the sandbox origin.
Rationale: Without these restrictions, the protocol becomes a phishing/malware hosting platform.
13.2 Content Indexing
- Unpublished sandbox content MUST NOT be publicly accessible without authentication.
- Published content MUST include
X-Robots-Tag: noindexuntil claimed. - Providers MUST NOT include sandbox URLs in sitemaps.
robots.txtalone is insufficient and MUST NOT be relied upon as a security control.
14. Content Rendering
Sandbox content is attacker-controlled.
14.1 Markdown Requirements
Markdown renderers MUST:
- Disable raw HTML entirely
- Strip
javascript:URLs - Strip
data:URLs - Strip all
styleattributes - Strip inline event handlers (
onclick,onerror, etc.) - Allowlist URL schemes (
https:only)
14.2 SVG Prohibition
SVG content MUST be disallowed entirely in sandbox and preview contexts.
Rationale: SVG is executable. SVG sanitizers fail constantly. The attack surface is not worth the capability.
14.3 CSS Prohibition
Custom CSS MUST NOT be allowed in sandbox or preview contexts.
Additionally, renderers MUST strip:
- Inline
styleattributes background-imageURLs in any form- CSS
url()functions - CSS expressions
14.4 External Resources
Images and external resources:
- MUST be proxied through provider infrastructure, OR
- MUST be disallowed entirely (upload only)
If proxied, the proxy MUST implement full SSRF protections (see §18).
Sandbox content MUST NOT be executable.
15. Handle Rotation
15.1 Rotation Requirements
Public sandbox handles MUST be treated as bearer secrets.
Mandatory rotation events:
| Event | Handle Rotation | Rationale |
|---|---|---|
| Publish | MUST rotate | Leaked preview URLs must not grant published access |
| Claim | MUST rotate | Leaked sandbox URLs must not grant workspace access |
Behavior:
- On rotation, the old handle becomes immediately invalid (404).
- Old handles MUST NOT redirect to new handles.
- Old handles MUST be tombstoned to prevent reuse.
Rationale: Without rotation, leaked preview URLs become permanent access vectors. Handles will leak through referrers, screenshots, logs, analytics, copy/paste, and link previews. Rotation limits the blast radius.
16. Preview Admin Surface Isolation
The preview admin UI renders attacker-controlled content and MUST be treated as hostile.
16.1 Origin Requirements
Preview admin UI MUST:
- Be served from a separate origin from real admin
- Use a separate cookie jar
- Be read-only by authorization, not just by UI
Preview admin endpoints:
- MUST be incapable of mutating state at the backend level
- MUST reject all state-changing requests regardless of CSRF protection status
- MUST NOT share any authentication state with real admin
16.2 Cookie Requirements
Preview session cookies:
- MUST be HttpOnly, Secure, SameSite=Strict
- MUST be scoped to the preview origin only
- MUST NOT be sent to real admin origins
One XSS in preview MUST NOT become admin compromise.
17. Preview Token Exchange Security
17.1 Exchange Code Requirements
Exchange codes MUST:
- Be single-use
- Expire within ≤10 minutes
- Be invalidated immediately upon use
- Be scoped to a single sandbox
17.2 Scanner Resistance
Exchange endpoints:
- MUST NOT consume codes on GET requests
- MUST NOT auto-submit or auto-consume codes under any circumstances
- MUST require a deliberate POST action initiated by a user gesture
- MUST NOT execute JavaScript that could trigger consumption
- MUST NOT allow open redirects
Implementation:
The exchange page MUST:
- Render static HTML with a form
- Require human click on a submit button
- Process consumption only on POST
- Never include JavaScript that could auto-submit
Providers SHOULD bind exchange codes to user agent characteristics to reduce cross-context replay.
17.3 Error Responses
Reused, expired, or invalid exchange codes MUST return identical responses. The response MUST NOT reveal:
- Whether the code ever existed
- Whether it was already used
- Whether it expired
18. SSRF and Outbound Fetch Protection
If the provider fetches user-supplied URLs:
18.1 Fetch Hardening
Fetchers MUST:
- Allowlist schemes (
https:only) - Block private IP ranges (RFC1918, link-local, loopback)
- Block cloud metadata endpoints explicitly
- Implement DNS rebinding protections
- Enforce size limits (e.g., 5MB)
- Enforce timeout limits (e.g., 10 seconds)
- Validate Content-Type
18.2 No Automatic Enrichment
Providers MUST NOT perform automatic metadata fetching, unfurling, oEmbed, or content introspection on user-supplied URLs in sandbox contexts.
This includes:
- Link previews
- OpenGraph extraction
- Image dimension detection
- Any "helpful" URL processing
Rationale: This is how SSRF re-enters systems months after initial hardening.
19. Claim Flow Security
Ownership transfer is the most sensitive operation in the protocol.
19.1 Claim Code Requirements
Claim codes MUST:
- Have ≥64 bits entropy (≥80 bits RECOMMENDED)
- Be single-use
- Expire within ≤1 hour
- Be scoped to a single sandbox
19.2 Claim Verification
Claim verification MUST require TWO factors:
- Claim code — proves possession of the code
- Proof-of-work — proves computational investment at claim time
The PoW challenge for claim:
- MUST be issued fresh at claim time
- MUST NOT reuse the sandbox creation challenge
- SHOULD use the same difficulty as sandbox creation
- MUST be validated atomically with the claim code
19.3 Rationale
PoW as second factor provides:
- Resistance to claim hijacking (attacker must be present and invest computation)
- No PII collection required before ownership transfer
- Symmetric cost model (agent pays to create, human pays to own)
- No external dependencies (email delivery, SMS gateways)
19.4 State Requirements
Claim verification MUST require the sandbox to still be in published state at verification time.
Race condition protections:
- Claim MUST fail if sandbox expires during verification
- Claim MUST fail if sandbox is deleted during verification
- Claim MUST be atomic with state transition
19.5 Verification Hardening
Claim verification endpoints MUST:
- Enforce rate limits per IP and per code
- Implement progressive lockout
- Avoid existence or validity oracles
- Perform constant-time comparisons
- Return identical responses for all failure modes
19.6 Optional Email Collection
Providers MAY collect email after successful claim for:
- Account recovery
- Notifications
- Marketing (with consent)
Email MUST NOT be required for claim verification itself.
19.4 Post-Claim Invalidation
Claim success MUST immediately invalidate:
- All sandbox tokens
- All preview sessions
- All outstanding exchange codes
- The old public handle (rotation)
20. Token Handling
20.1 Agent Tokens
Agent tokens MUST be:
- Sandbox-scoped
- Short-lived (≤48 hours)
- Non-refreshable
- Incapable of minting non-sandbox credentials
Implementations SHOULD support DPoP or equivalent proof-of-possession.
20.2 Client Tokens
Client tokens (for idempotency):
- MUST be used only for idempotency
- MUST NOT be treated as identity
- Abuse prevention MUST NOT rely on client tokens
21. CSRF, Clickjacking, and Redirect Protection
- State-changing endpoints MUST be protected against CSRF.
- Claim and preview surfaces MUST set
X-Frame-Options: DENYand CSPframe-ancestors 'none'. - Redirect targets MUST be fixed or allowlisted.
- User-controlled redirect parameters MUST NOT be honored.
22. Logging Requirements
Providers MUST NOT log:
- Tokens
- Claim codes
- Exchange codes
- Authorization headers
Providers MUST log:
request_id- Action type
- Internal sandbox ID (not public handle)
- Coarse abuse signals (IP range, not full IP where possible)
Providers MUST ensure that log entries cannot be correlated to reconstruct secrets.
23. Abuse Considerations
23.1 Economic Model
Attackers will attempt to use this protocol for:
- Spam hosting
- Phishing pages
- Malware distribution
- SEO manipulation
- Credential harvesting
Providers MUST assume:
- PoW will be pipelined and amortized
- Botnets will be used
- Abuse will be automated
23.2 Required Mitigations
| Attack | Mitigation |
|---|---|
| Mass sandbox creation | Adaptive PoW, behavioral analysis |
| Content abuse | Content scanning, rate limiting publication |
| Domain reputation damage | Handle rotation, noindex, rapid takedown |
| Preview link harvesting | Short TTLs, exchange interstitials |
| Claim hijacking | High entropy, PoW second factor, lockout |
23.3 Monitoring
Providers SHOULD monitor:
- Sandbox creation velocity
- Publication rate
- Content similarity (spam detection)
- Geographic anomalies
- Claim failure rates
24. Compliance Criteria
An implementation claiming AHP compliance is non-compliant if it:
- Allows guessable sandbox URLs (<128 bits entropy)
- Renders untrusted content in privileged origins
- Allows sandbox tokens to mint durable credentials
- Exposes claim verification oracles
- Relies on rate limiting as sole abuse defense
- Allows unclaimed sandbox content to be accessed without authentication
- Does not rotate handles on publish and claim
- Allows SVG content in sandbox contexts
- Performs automatic URL unfurling or metadata fetching
- Allows exchange codes to be consumed without human interaction
Any implementation that allows unclaimed sandbox content to be accessed without authentication is non-compliant.
Part 4: Implementation Profile (ReplyRaptor)
This section is informative and specific to ReplyRaptor's implementation.
25. ReplyRaptor Content Type: FAQ
{
"id": "faq_...",
"sandbox_id": "sbx_...",
"title": "string, max 100",
"slug": "string, URL-safe",
"description": "string, max 500",
"questions": [
{
"id": "q_...",
"question": "string, max 500",
"answer": "string, max 10KB, safe Markdown only",
"order": "integer"
}
],
"settings": {
"theme": "light | dark | auto",
"accent_color": "#hex",
"show_search": "boolean",
"show_feedback": "boolean"
},
"status": "draft | published"
}
Disallowed in sandbox:
- Custom CSS
- SVG content
- External image URLs
- Raw HTML in answers
styleattributesdata:URLs
26. ReplyRaptor Origins
| Surface | Origin |
|---|---|
| Published FAQ | {handle}.faq.replyraptor.net |
| Preview content | preview.replyraptor.net |
| Preview admin | preview-admin.replyraptor.net |
| Real admin | admin.replyraptor.com |
| API | api.replyraptor.com |
Note: Different registrable domains for preview vs production admin.
27. ReplyRaptor Identifiers
| Identifier | Format | Entropy | Rotates |
|---|---|---|---|
sandbox_id | sbx_{22 base62} | 128 bits | No |
public_handle | {22 base62} | 128 bits | Yes (publish, claim) |
agent_token | rr_sbx_{43 base62} | 256 bits | No (invalidated) |
claim_code | RAPTOR-{4}-{4}-{4}-{4} | ~82 bits | N/A |
exchange_code | rr_exch_{22 base62} | 128 bits | N/A |
28. ReplyRaptor Limits
| Resource | Limit |
|---|---|
| Sandbox TTL | 48 hours |
| Max extensions | 2 × 24 hours |
| FAQs per sandbox | 5 |
| Questions per FAQ | 50 |
| Answer size | 10 KB |
| Requests per hour | 500 |
29. ReplyRaptor Admission
- Method: Adaptive Proof-of-Work
- Algorithm: SHA-256 leading zeros
- Base difficulty: 20 bits
- Elevated difficulty: Up to 28 bits under abuse
- Challenge TTL: 5 minutes
30. ReplyRaptor Handle Rotation
| Event | Before | After |
|---|---|---|
| Create | N/A | abc123... (preview handle) |
| Publish | abc123... | def456... (published handle) |
| Claim | def456... | ghi789... (workspace handle) |
Old handles return 404 immediately. No redirects.
Appendix A: Example Flow
Agent Provider
│ │
│ GET /v1/sandboxes/challenge │
│─────────────────────────────────────>│
│ │
│ { challenge, difficulty: 20 } │
│<─────────────────────────────────────│
│ │
│ [solve PoW, ~1-2 seconds] │
│ │
│ POST /v1/sandboxes │
│ { challenge, nonce } │
│─────────────────────────────────────>│
│ │
│ { id, public_handle: "abc...", │
│ agent_token } │
│<─────────────────────────────────────│
│ │
│ POST /v1/faqs │
│─────────────────────────────────────>│
│ │
│ { faq_id } │
│<─────────────────────────────────────│
│ │
│ POST /v1/faqs/{id}/publish │
│─────────────────────────────────────>│
│ │
│ { published_url, │
│ new_handle: "def..." } ◄─────────│── HANDLE ROTATED
│<─────────────────────────────────────│
│ │
│ [Agent shows human published URL] │
│ [Human reviews, approves] │
│ │
│ POST /v1/sandboxes/{id}/claim │
│─────────────────────────────────────>│
│ │
│ { claim_code, claim_url } │
│<─────────────────────────────────────│
│ │
│ [Human enters code + confirms email]│
│ │
│ ──────────────────│── HANDLE ROTATED
│ ──────────────────│── ALL TOKENS INVALIDATED
│ ──────────────────│── SANDBOX → WORKSPACE
│ │
Appendix B: Security Checklist
Before claiming AHP 1.0 compliance:
Identifiers:
- Public handles ≥128 bits entropy
- Claim codes ≥64 bits entropy (≥80 recommended)
- Handles rotate on publish
- Handles rotate on claim
- Old handles return 404 (no redirect)
Admission:
- PoW or equivalent required
- PoW difficulty is adaptive
- Behavioral throttling implemented
Content:
- SVG disallowed entirely
- Raw HTML stripped
- Custom CSS disallowed
- Style attributes stripped
- data: URLs stripped
- javascript: URLs stripped
- Only https: URLs allowed
Preview:
- Separate origin from real admin
- Different registrable domain recommended
- Read-only enforced at backend
- Exchange requires human gesture (POST)
- Exchange codes single-use, ≤10 min TTL
Claim:
- Two-factor (code + PoW) implemented
- Rate limiting per IP and per code
- Progressive lockout
- Constant-time comparison
- State checked at verification time
Observability:
- Error responses identical for all failure modes
- No existence oracles
- Timing normalized
- Secrets not logged
Hosting:
- Arbitrary paths not routed
- Cannot serve arbitrary HTML/JS
- noindex on unpublished content
Appendix C: Changelog
| Version | Date | Changes |
|---|---|---|
| 0.1.0 | 2026-01-23 | Initial draft |
| 0.2.0 | 2026-01-23 | Security hardening |
| 0.3.0 | 2026-01-23 | Comprehensive security considerations |
| 1.0.0-draft | 2026-01-23 | Protocol extraction |
| 1.0.0-rc1 | 2026-01-23 | Handle rotation, adaptive PoW, SVG ban, no-auto-consume, observability rules, abuse considerations |