EEP Specification

Version: 0.1-draft  |  Status: Pre-Release  |  License: Apache 2.0

Canonical normative text lives in the main EEP repository at docs/current/SPECIFICATION.md. This page summarizes core protocol behavior for quick navigation; if anything disagrees with that file, the repository wins.

Abstract

The Entity Engagement Protocol (EEP) defines how digital entities publish real-time state change events and how authorized subscribers receive them. It uses three transport layers: state resolution (REST), signal stream (SSE and Webhooks), and network pulse (WebSockets). EEP supports the agentic web, where AI agents participate directly in digital interactions.

1. Terminology

TermDefinition
EntityAny digital subject with a stable identity and state that can change over time (a person, business, AI agent, or product)
SourceThe entity or platform originating an event, identified by a DID or URI
PublisherThe platform responsible for emitting events on behalf of entities
SubscriberAn agent, service, or system that has subscribed to receive events
EventA structured, immutable record of a state change at a specific point in time
DIDDecentralized Identifier (W3C standard) for globally identifying entities
HMACHash-based Message Authentication Code, used to sign webhook payloads

2. Architecture Overview

A publisher emits events into an internal bus; subscribers receive them over the signal stream (SSE and webhooks) and optionally over the network pulse (WebSockets). The diagram shows three fan-out paths, not a fourth unnamed channel.

EEP publisher
Any EEP-compliant platform
EEP event bus
Redis Streams / RabbitMQ (example)
SSE stream
Layer 2a
Webhooks
Layer 2b
WebSockets
Layer 3

3. Layer 1: State Resolution

State resolution allows agents to discover and read the current state of an entity.

3.1 Entity Resolution Endpoint

GET /:type/:username
Accept: application/json | text/markdown | text/toon

A compliant publisher MUST serve at minimum JSON (structured entity profile with capabilities, trust score, DID document) and Markdown (human-readable representation for LLM consumption).

3.2 Required Response Headers

HTTP/1.1 200 OK
Content-Type: application/json
EEP-Version: 0.1
EEP-Entity-DID: did:web:example.com:u:acme-corp
Link: <https://api.example.com/eep/subscribe>; rel="subscribe"; type="application/json"
Link: <https://api.example.com/eep/stream?source=acme-corp>; rel="monitor"
Link: </.well-known/agent.json>; rel="agent-card"

3.3 Capability Declaration

{
  "eep": {
    "version": "0.1",
    "endpoint": "https://api.example.com/eep",
    "supported_delivery": ["webhook", "sse"],
    "supported_event_types": ["com.example.entity.*", "com.example.trust.*"],
    "identity": {
      "did": "did:web:example.com:u:acme-corp",
      "verification_endpoint": "https://api.example.com/did/acme-corp"
    },
    "gated": true,
    "gates_url": "https://api.example.com/eep/gates/did:web:example.com:u:acme-corp",
    "commerce": true,
    "services_url": "https://api.example.com/eep/services/did:web:example.com:u:acme-corp"
  }
}

3.4 Gated Access

Entities MAY define gates to restrict access to resources. A gate configuration has entity-defined tiers, each with a list of requirements and a set of access patterns.

Standard Requirement Types

TypeDescriptionProof Needed
credentialW3C Verifiable Credential from a named issuer DIDEncoded VC signed by specified issuer
identityProof of DID ownership (know-your-peer)Signed challenge from agent's DID key
agreementCryptographic signature over SHA-256 hash of a licence documentEdDSA signature + Verifiable Presentation
data_requestQuid-pro-quo: agent provides specific claims about itself/ownerSigned VP with W3C DPV purpose declaration
paymentOn-chain micropayment to publisher addressVerified transaction hash from compatible L1/L2
combinedAND/OR combination of any of the aboveAll constituent proofs

Access Restriction Response (402)

{
  "error": "access_restricted",
  "resource": "content.papers.full_text",
  "current_tier": "public",
  "required_tier": "academic",
  "unmet_requirements": [
    {
      "type": "credential",
      "resolution_hint": "Verifiable Credential required: AcademicAffiliation"
    }
  ],
  "gates_config_url": "https://api.example.com/eep/gates/did:web:example.com:u:alice"
}

4. Layer 2: Signal Stream (SSE)

4.1 SSE Endpoint

GET /eep/stream
Authorization: Bearer {API_KEY}
Accept: text/event-stream
ParameterTypeRequiredDescription
sourcestringNoFilter by entity username or DID
eventsstringNoComma-separated event type filter with wildcard support
last_event_idstringNoResume from this event ID

4.2 Guaranteed Delivery via Last-Event-ID

A compliant EEP publisher MUST implement event replay. When a subscriber reconnects with the Last-Event-ID header, the server MUST replay all events after that ID, up to a configurable retention window (minimum: 24 hours).

4.3 Heartbeat

The publisher MUST send a comment heartbeat every 15 seconds to detect stale connections:

: heartbeat 2026-02-22T14:30:00Z

5. Layer 2: Signal Stream (Webhooks)

5.1 Webhook Subscription

POST /eep/subscribe
Authorization: Bearer {API_KEY}
Content-Type: application/json

{
  "source_did": "did:web:example.com:u:acme-corp",
  "event_types": ["com.example.entity.updated", "com.example.trust.*"],
  "delivery_method": "webhook",
  "delivery_url": "https://agent.example.com/hooks/eep",
  "delivery_format": "cloudevents/v1.0"
}

5.2 Webhook Signature Verification

The webhook-signature header contains an HMAC-SHA256 signature over:

{webhook-id}.{webhook-timestamp}.{raw-body}

Receiving platforms MUST use crypto.timingSafeEqual() for constant-time comparison and reject timestamps outside the 60-second replay window.

5.3 Retry Policy

AttemptDelay
1Immediate
25 seconds
330 seconds
42 minutes
515 minutes
61 hour
76 hours

6. Layer 3: Network Pulse (WebSockets)

6.1 Message Format

{
  "v": 1,
  "type": "entity | a2a | system | chat | commerce",
  "action": "specific-action",
  "seq": 12345,
  "data": {}
}

6.2 JWT Re-authentication

Server → Client: { "type": "system", "action": "auth_expiring", "data": { "expires_in": 300 } }
Client → Server: { "type": "system", "action": "auth_refresh", "data": { "token": "new-jwt" } }
Server → Client: { "type": "system", "action": "auth_refreshed", "data": { "expires_at": "..." } }

If the client fails to refresh within 60 seconds, the server MUST close with code 4001.

6.3 Chat Messages

ActionDirectionDescription
sendClient → ServerSend a message (max 4096 chars). Persisted and broadcast.
historyClient → ServerRequest message history with cursor-based pagination.
readClient → ServerMark messages as read.

7. Event Envelope Format

All EEP events MUST be valid CloudEvents v1.0.2 envelopes with EEP-specific extensions:

{
  "specversion": "1.0",
  "id": "unique-event-id",
  "source": "did:web:example.com:u:acme-corp",
  "type": "com.example.entity.updated",
  "time": "2026-02-22T14:30:00Z",
  "datacontenttype": "application/json",
  "eep_version": "0.1",
  "eep_subscription_id": "sub_01HN3QK7GX",
  "eep_trust_score": 87,
  "eep_actor_type": "human | agent | system | cron",
  "data": {}
}
AttributeTypeRequiredDescription
eep_versionstringMUSTEEP spec version
eep_subscription_idstringSHOULDSubscription this was delivered to
eep_trust_scoreintegerSHOULDEntity's trust score at event time
eep_actor_typestringSHOULDWho triggered the event

8. Event Type Naming Convention

EEP event types follow a reverse-domain dot notation pattern:

{reverse-domain}.{entity-type}.{action}
{reverse-domain}.{entity-type}.{sub-domain}.{action}

Examples:
  com.example.entity.updated
  com.example.trust.changed
  com.example.content.published
  com.example.commerce.offer

Wildcard matching: com.example.entity.* matches all entity events. Only prefix matching is supported.

9. Standard Event Catalog

Entity Lifecycle

Event TypeDescription
com.example.entity.createdA new entity profile was created
com.example.entity.updatedOne or more profile fields changed
com.example.entity.deletedPermanently deleted
com.example.entity.activatedA deactivated entity was reactivated
com.example.entity.deactivatedTemporarily deactivated

Trust and Identity

Event TypeDescription
com.example.trust.changedTrust score changed
com.example.trust.signal.addedA trust signal was recorded
com.example.identity.verifiedVerification completed
com.example.identity.did_updatedDID document updated

Commerce and Marketplace

Event TypeDescription
com.example.commerce.offerA new price offer was made
com.example.commerce.counterA counter-offer was made
com.example.commerce.acceptedNegotiation accepted
com.example.commerce.invoicedInvoice generated
com.example.commerce.paidPayment confirmed
com.example.commerce.completedTransaction completed
com.example.service.listedNew service published
com.example.gate.config_changedGate configuration updated

10. Subscription Lifecycle

  1. SubscribePOST /subscribe creates state pending_verification.
  2. Publisher sends a GET verification challenge to the subscriber's delivery_url.
  3. Verification outcome:
    • Successactive
    • Failurerejected
  4. While active: deliver events. After 5 consecutive delivery failures paused. Use POST /subscriptions/:id/resume to return to active.

11. Authentication and Authorization

EEP uses two complementary authentication mechanisms:

  • DID-based cryptographic identity (primary) — agents present a W3C DID and sign gate requirement proofs (Verifiable Credentials, challenge responses, payment hashes). This is the canonical zero-trust auth model.
  • API key (convenience) — for simple subscriptions without gate requirements, Bearer token auth is accepted.
// Simple subscription — API key
Authorization: Bearer {API_KEY}

// Gated resource — DID proof in request body
POST /eep/gate/proof
{ "type": "identity", "did": "did:web:agent.example.com", "signature": "..." }

Scopes

ScopeDescription
read:subscriptionsList own subscriptions
write:subscriptionsCreate and manage subscriptions
read:eventsAccess the SSE stream
read:gatesRead gate configurations
write:gatesModify gate configurations
commerce:negotiateParticipate in commerce negotiations
read:servicesBrowse service listings
write:servicesPublish and manage service listings

12. Discovery

Subscribers discover EEP endpoints through three mechanisms:

  1. HTTP Link header — every entity resolution response includes Link: <...>; rel="subscribe"
  2. Agent card extension — A2A agent card includes x-eep extension
  3. Well-known documentGET /.well-known/eep.json returns platform capabilities

13. Rate Limiting

Publishers MUST enforce rate limits and return standard headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1708168200
Retry-After: 120
ActionLimit
Subscription creation100/day
SSE connections5 concurrent
Webhook deliveries received10,000/day
Event stream history queries60/hour

14. Conformance Levels

LevelRequirements
CoreLayer 1 (REST state) + Layer 2 SSE. Suitable for read-only publishers, IoT sensors, knowledge bases.
StandardCore + Webhooks + HMAC-SHA256 signing + credential and payment gates + version negotiation. Suitable for B2B data APIs, financial feeds.
FullStandard + Layer 3 WebSockets + commerce state machine + agreement + data_request gates + session persistence + W3C DPV privacy declarations. Suitable for agent commerce, regulated industries.

15. Service Discovery and Marketplace

Entities MAY publish a service catalog of their offerings.

Service Listing Billing Models

The pricing.model field on a service listing declares how recurring or metered charges work:

ModelDescription
fixedOne-time flat price
per_requestCharge per API request
subscriptionRecurring charge with a billing period
meteredUsage-based billing
tiered_volumeVolume discounts with tier brackets
x-*Custom billing models

Commerce Price Discovery Modes (Whitepaper §8.4)

Separate from billing models, the commerce state machine supports three price discovery modes that govern how agent and entity reach agreement on price during a WebSocket negotiation:

ModeDescription
fixedPublisher sets a non-negotiable price. Agent accepts or walks away.
negotiatedBilateral offer/counter over WebSocket until both sides accept.
auctionPublisher broadcasts an RFP; agents submit bids; publisher selects winner.

Commerce Negotiation State Machine

Negotiation

offer[open]counter[countered] accept[accepted]

  • From [countered]: reject[rejected]
  • From [open]: expire[expired]

Fulfillment

[accepted]invoice[invoiced]receipt [paid]complete[completed]

Exception

Any active state → dispute[disputed]

Terminal states: rejected, expired, completed.