Skip to content

SEMP Protocol Specification

Version: 0.1
Status: Draft
Last Updated: January 2025

SEMP (Semantic Environment Messaging Protocol) is a protocol for stigmergic agent coordination through semantic events and signal-based communication.

Agents coordinate indirectly through environmental signals, similar to pheromone trails in ant colonies:

  • Indirect Communication - No direct agent-to-agent messages
  • Environmental Signals - Shared signal field for coordination
  • Emergent Behavior - Complex patterns from simple rules
  • Self-Organization - System adapts without central control

SEMP defines five semantic event types for complete agent lifecycle coordination:

TypePurposeSignal Effect
proposalAgent suggests actionInitialize signal (S = 0.3)
readyAgent completes workMaintain signal
testValidation/QA eventMaintain signal
rewardPositive feedbackAmplify signal (S × α)
penaltyNegative feedbackReduce signal (S - │v│)
{
"id": "uuid",
"type": "proposal | ready | test | reward | penalty",
"scope": "string",
"trace_id": "string",
"agent_id": "string",
"parent_ids": ["uuid", "uuid"], // optional
"timestamp": "ISO 8601",
"payload": {}
}
  • Type: UUID v4
  • Generated By: Server
  • Purpose: Unique event identifier
  • Type: Enum
  • Values: proposal, ready, test, reward, penalty
  • Purpose: Event classification
  • Type: String
  • Format: Hierarchical dot-notation
  • Examples:
    • ui.login
    • api.users.create
    • workflow.task1.subtask2
  • Purpose: Event categorization and signal routing
  • Type: String
  • Purpose: Causality tracking across event chains
  • Example: Single trace_id for all events in a workflow
  • Type: String
  • Purpose: Identify the agent that created the event
  • Format: Free-form (framework-specific)
  • Type: Array of UUID
  • Purpose: Event dependency graph
  • Use Case: Event B depends on Event A completion
  • Type: ISO 8601 string
  • Generated By: Server
  • Purpose: Event ordering and decay calculation
  • Type: Object
  • Purpose: Event-specific data
  • Validation: Varies by event type

Agent proposes an action or change to the environment.

Payload Schema:

{
"action": "string", // required
"params": {}, // optional
"estimated_effort": "number", // optional (hours)
"priority": "low|medium|high" // optional
}

Example:

{
"type": "proposal",
"scope": "ui.login",
"trace_id": "trace-001",
"agent_id": "agent-langgraph-1",
"payload": {
"action": "improve_ux",
"params": {
"target": "button_visibility"
},
"priority": "high"
}
}

Signal Behavior:

  • Creates signal if not exists: {scope}:{action}
  • Initial strength: 0.3
  • Alpha: 1.2, Lambda: 0.95

Agent signals completion and readiness for next phase.

Payload Schema:

{
"status": "completed", // required
"result": {}, // optional
"next_action": "string" // optional
}

Example:

{
"type": "ready",
"scope": "ui.login",
"trace_id": "trace-001",
"agent_id": "agent-langgraph-1",
"parent_ids": ["proposal-event-id"],
"payload": {
"status": "completed",
"result": {
"changes_made": ["increased_button_size"]
},
"next_action": "test"
}
}

Signal Behavior:

  • Maintains existing signal
  • No strength modification
  • Updates last_updated timestamp

Validation, quality assurance, or verification event.

Payload Schema:

{
"status": "running|passed|failed", // required
"suite": "string", // optional
"coverage": "number", // optional (0-100)
"failures": [] // optional
}

Example:

{
"type": "test",
"scope": "ui.login",
"trace_id": "trace-001",
"agent_id": "agent-playwright-1",
"parent_ids": ["ready-event-id"],
"payload": {
"status": "passed",
"suite": "e2e",
"coverage": 95.5,
"failures": []
}
}

Signal Behavior:

  • Maintains existing signal
  • Test results can trigger reward/penalty

Positive feedback to amplify successful patterns.

Payload Schema:

{
"value": "number", // required (0.0 to 1.0)
"α": "number", // optional (default: 1.2)
"reason": "string" // optional
}

Example:

{
"type": "reward",
"scope": "ui.login",
"trace_id": "trace-001",
"agent_id": "agent-supervisor",
"parent_ids": ["test-event-id"],
"payload": {
"value": 0.8,
"α": 1.5,
"reason": "tests_passed_with_high_coverage"
}
}

Signal Behavior:

S_new = min(1.0, S_old + (value × α))

Negative feedback to dampen inefficient behaviors.

Payload Schema:

{
"value": "number", // required (negative value)
"reason": "string" // optional
}

Example:

{
"type": "penalty",
"scope": "ui.login",
"trace_id": "trace-001",
"agent_id": "agent-supervisor",
"parent_ids": ["test-event-id"],
"payload": {
"value": -0.3,
"reason": "test_failures_detected"
}
}

Signal Behavior:

S_new = max(0.0, S_old - |value|)
{
"id": "uuid",
"scope": "string",
"pattern": "string",
"strength": "number", // 0.0 to 1.0
"last_updated": "ISO 8601",
"alpha": "number", // amplification factor
"lambda": "number" // decay factor
}

Signals are indexed by: {scope}:{pattern}

Example:

  • Event: {scope: "ui.login", payload: {action: "improve_ux"}}
  • Signal Key: ui.login:improve_ux
S_new = min(1.0, S_old + (reward_value × α))
Where:
α (alpha) = amplification factor (default: 1.2)
reward_value = payload.value (0.0 to 1.0)

Example:

S_old = 0.5
reward_value = 0.8
α = 1.2
S_new = min(1.0, 0.5 + (0.8 × 1.2))
S_new = min(1.0, 0.5 + 0.96)
S_new = min(1.0, 1.46)
S_new = 1.0
S_new = max(0.0, S_old - |penalty_value|)
Where:
penalty_value = payload.value (negative)

Example:

S_old = 0.8
penalty_value = -0.3
S_new = max(0.0, 0.8 - 0.3)
S_new = 0.5

Signals naturally decay over time to prevent stale patterns:

S_new = S_old × λ
Where:
λ (lambda) = decay factor (default: 0.95)

Decay Job:

  • Runs every 60 seconds
  • Applies decay to all signals
  • Removes signals when S < 0.01

Example:

Initial: S = 1.0
After 1 min: S = 1.0 × 0.95 = 0.95
After 2 min: S = 0.95 × 0.95 = 0.9025
After 3 min: S = 0.9025 × 0.95 = 0.857
...
After 20 min: S ≈ 0.358
After 40 min: S ≈ 0.128
After 60 min: S ≈ 0.046
After 80 min: S ≈ 0.016
After 90 min: S ≈ 0.009 → Removed
1. [Initialization]
→ proposal/ready/test event
→ Signal created (S = 0.3)
2. [Amplification]
→ reward event
→ S = S + (value × α)
3. [Reduction]
→ penalty event
→ S = S - |value|
4. [Decay] (every 60s)
→ S = S × λ
5. [Cleanup]
→ if S < 0.01: remove signal

All events in a workflow share the same trace_id:

trace-001:
- proposal (agent-1)
- ready (agent-1)
- test (agent-2)
- reward (agent-supervisor)

Events can reference parent events via parent_ids:

Event A (proposal):
{
"id": "a1b2c3",
"type": "proposal",
...
}
Event B (ready):
{
"id": "d4e5f6",
"type": "ready",
"parent_ids": ["a1b2c3"],
...
}
Event C (test):
{
"id": "g7h8i9",
"type": "test",
"parent_ids": ["d4e5f6"],
...
}

Parent IDs create a directed acyclic graph (DAG):

proposal
ready
test
╱ ╲
▼ ▼
reward penalty

Base URL: http://localhost:5000/api

Endpoints:

  • POST /events - Create event
  • GET /events - Get recent events
  • GET /events/scope/:scope - Filter by scope
  • GET /events/trace/:traceId - Filter by trace
  • GET /signals - Get all signals

URL: ws://localhost:5000/ws

Message Format:

{
"type": "event",
"data": {
"id": "uuid",
"type": "proposal",
...
}
}

Client Example:

const ws = new WebSocket('ws://localhost:5000/ws');
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.type === 'event') {
console.log('New event:', message.data);
}
};
  • Use hierarchical dot notation
  • Start specific → general: ui.login.button not button.login.ui
  • Keep under 64 characters
  • Use lowercase, underscores for spaces

Good:

  • api.users.create
  • workflow.data_processing.step1
  • ui.dashboard.chart_rendering

Bad:

  • CreateUsers (not hierarchical)
  • ui_dashboard_chart_rendering (use dots)
  • X (too generic)
  • Generate once per workflow
  • Use UUID or nanoid
  • Include in all related events
  • Enables end-to-end tracing

Alpha (α) - Amplification Factor:

  • Default: 1.2
  • Conservative: 1.1 (slow amplification)
  • Aggressive: 1.5 (fast amplification)

Lambda (λ) - Decay Factor:

  • Default: 0.95 (90 min to cleanup)
  • Slow decay: 0.98 (3 hours to cleanup)
  • Fast decay: 0.90 (45 min to cleanup)

Client:

  • Validate events before sending
  • Handle 400 Bad Request (validation errors)
  • Retry on 5xx errors with exponential backoff
  • Use WebSocket reconnection logic

Server:

  • Return descriptive error messages
  • Use appropriate HTTP status codes
  • Log all validation failures

Current: SEMP v0.1

Future Versions:

  • v0.2: Add cancel event type
  • v0.3: Nested scope queries
  • v1.0: Stable protocol specification

Current (v0.1):

  • No authentication (open platform)
  • Input validation only (Zod)
  • HTTPS/WSS recommended

Future:

  • JWT-based authentication
  • Per-event authorization
  • Rate limiting
  • Audit logging

See Integration Guide for complete examples with:

  • LangGraph
  • CrewAI
  • AutoGen
  • Custom agents