Skip to main content
Version: v0.9.0a2
Spec

Spec-19-Adapter-ABI

6 min readSpec contributor · Adapter authorProcess + middleware contract

What this page is

Rendered compatibility entry point for Spec-19-Adapter-ABI. Minimum contract for platform adapters: env vars, assert/query, source binding.

Authoritative source: spec/stigmem-spec-v0.9.0a1.md

Section body

Each subsection below shows the most recent normative text from the spec source.

pre-reset status.

Promoted from the pre-reset design work reserved section to normative spec, grounded in the three pre-reset adapters shipped: MCP (stigmem/adapters/mcp/), Paperclip (stigmem/adapters/paperclip/), and OpenClaw (stigmem/adapters/openclaw/).

§12.1 Adapter archetypes

The ABI recognizes two adapter archetypes with different startup failure contracts.

Archetype
Example
Failure contract
Process-mode adapter
MCP server.ts
A standalone process whose sole purpose is to bridge a platform protocol to Stigmem. The process is useless if Stigmem is not configured; fast failure is correct behavior.
Middleware adapter
Paperclip hook.sh · OpenClaw adapter.py
Code that extends an existing agent runtime. Stigmem is optional; the agent MUST continue operating if Stigmem is unconfigured or unreachable.

§12.2 Required environment variables

All adapters MUST honor the following environment variables.

Variable
Required by · Default
Description
STIGMEM_URL
All · —
Base URL of the Stigmem node, e.g. http://localhost:8765.
STIGMEM_API_KEY
All (optional) · none
API key; required when auth=required.
STIGMEM_SOURCE_ENTITY
Middleware · adapter-specific
Entity URI used as source on all write operations. Adapters SHOULD default to a descriptive identity; "agent:unknown" is an acceptable last-resort fallback.

Process-mode adapters: MUST exit with a non-zero status code and a clear error message to stderr if STIGMEM_URL is absent.

Middleware adapters: MUST silently skip all Stigmem operations if STIGMEM_URL is absent. MUST NOT modify the agent process exit code.

§12.3 Boot handshake protocol

The boot handshake runs once when the adapter initializes. It has two phases: a node probe and (for middleware adapters) a context pull.

§12.3.1 Node probe

Adapters SHOULD issue GET /.well-known/stigmem to verify node reachability on startup.

Expected response shape:

{
"version": "0.8",
"node_id": "<URI>",
"node_url": "<string>",
"auth": "none" | "required",
"federation": "disabled" | "enabled"
}

Required fields: version, node_id, node_url, auth, federation.

If the probe fails or required fields are absent:

Archetype
On probe failure
Recovery
Process-mode
log error to stderr
SHOULD NOT crash — allow individual tool invocations to fail with a StigmemError rather than killing the process.
Middleware
log warning to stderr
MUST return an empty BootContext. MUST NOT crash or alter the agent's exit code.

§12.3.2 Context pull (middleware adapters only)

After a successful node probe, middleware adapters that inject context into the agent system prompt MUST issue the following queries in order. All queries are non-fatal: a failed or empty response on any individual query MUST NOT abort the boot sequence.

  1. User entity facts. GET /v1/facts?entity={user_entity}&scope=company&min_confidence=0.7. Adapters SHOULD filter the result to relevant relation namespaces (e.g. preference:).
  2. Project constraints. One query per project entity; skip if no project entities configured: GET /v1/facts?entity={project_entity}&relation=roadmap:constraint&scope=company&min_confidence=0.7.
  3. Pending handoffs targeting this adapter. GET /v1/facts?relation=intent:handoff_to&scope=company&min_confidence=0.8. Filter client-side to facts where value.v == STIGMEM_SOURCE_ENTITY.
  4. Recent escalations. GET /v1/facts?relation=intent:escalation&scope=company&min_confidence=0.8&limit=10.

§12.3.3 BootContext shape

BootContext {
facts: Fact[] // all successfully retrieved facts; empty list if node unreachable
summary: string // markdown-formatted context for system prompt injection (see §12.5)
}

BootContext is always returned, even on total failure. A failed boot returns BootContext { facts: [], summary: "" }.

§12.4 Write surfaces

Adapters MUST assert the following facts on the specified lifecycle events.

Write invariants (apply to all assertions).

confidence MUST be 1.0 unless a per-surface override is listed. All write calls MUST use fire-and-forget semantics: errors MUST be suppressed; the adapter MUST NOT crash the agent on write failure. Write failures SHOULD be logged to stderr at warning level.

§12.4.1 Paperclip-style lifecycle facts

For adapters that instrument platform issue/task lifecycle.

Event
Relation · Value · Scope
Notes
Checkout (task claimed)
paperclip:checkout · "in_progress" · company
Entity: issue:{task_id}.
Completion
paperclip:issue_status · "done" · company
Blocked
paperclip:issue_status · "blocked" · company
Blocked by (optional)
paperclip:blocked_by · ref · company
Value: "issue:{blocking_id}".
Activity ping
paperclip:last_active · datetime · local
Activity pings MUST use scope="local" — heartbeat signals for intra-node observability; MUST NOT be federated.

Entity URI format note: The entity column above uses informal URI shorthand (issue:{task_id}). Per §2.5, adapters targeting pre-reset+ SHOULD use formal URIs: stigmem://{node_authority}/issue/{task_id}. Migration tracked for pre-reset.

§12.4.2 Handoff facts

Emitted when an agent session ends or delegates to another agent. Mint a synthetic entity handoff:{uuid} and assert all of the following.

Relation
Type · Required?
Value
intent:handoff_to
ref · REQUIRED
Target agent entity URI.
intent:handoff_summary
text · REQUIRED
Human-readable summary (≤ 4 KB).
intent:context_ref
ref · ≥1 if fact_refs non-empty
Fact ID URI per referenced context fact (one assertion per ref).
intent:continuation
text · OPTIONAL
Continuation note; omit if absent.

All confidence 1.0, scope company.

§12.4.3 Decision facts

Emitted when an agent makes a significant architectural or roadmap choice.

Entity
Relation · Type · Value
Scope · confidence
{decision_entity}
roadmap:decision · text · summary (≤4 KB)
company · 1.0

The {decision_entity} SHOULD be a formal URI: stigmem://{node_authority}/decision/{slug}.

§12.4.4 Escalation facts

Emitted when an agent cannot proceed and must escalate. Mint a synthetic entity escalation:{uuid} and assert all three.

Relation
Type
Value (all REQUIRED)
intent:escalation
string
Priority: "low" | "medium" | "high" | "critical".
intent:escalate_to
ref
Target agent or user entity URI.
intent:goal
text
Goal statement describing what the agent could not complete (≤ 2 KB).

All confidence 1.0, scope company.

§12.4.5 Minimum confidence and scope requirements summary

Fact class
Min confidence · Required scope
Notes
Lifecycle status
1.0 · company
paperclip:checkout, paperclip:issue_status, paperclip:blocked_by.
Activity ping
1.0 · local (never federated)
paperclip:last_active.
Handoff / Decision / Escalation facts
1.0 · company

Adapters MUST NOT write lifecycle or intent facts with confidence below 1.0. Low-confidence writes on these relations would pollute conflict resolution and break downstream agents that depend on these facts for routing.

§12.5 Context injection format

Adapters that inject Stigmem facts into an agent's system prompt MUST use the following markdown schema.

## Stigmem context — {user_entity}

### {namespace}
- **{relation}** on `{entity}`: {value_str}[ _(confidence: {confidence:.2f})_]

{user_entity}

The primary entity passed to the boot handshake.

{namespace}

The relation prefix before the first :; facts grouped under shared ### {namespace}.

{relation}

The fact's relation field, verbatim.

{entity}

The fact's entity field, verbatim.

{value_str}

For null type → render (null); for others → render value.v as string.

Confidence annotation

Rendered only when confidence < 1.0, as (confidence: {value:.2f}).

Ordering: Facts SHOULD be ordered by descending confidence, then descending hlc within equal confidence.

Empty context.

If no facts were retrieved, adapters MUST return an empty string and MUST NOT inject the ## Stigmem context header. Do not inject a header with zero fact lines.

Reference implementation (stigmem/adapters/openclaw/adapter.py:_facts_to_summary):

def _facts_to_summary(facts: list[Fact], user_entity: str) -> str:
if not facts:
return ""
groups: dict[str, list[Fact]] = {}
for fact in facts:
ns = fact.relation.split(":")[0] if ":" in fact.relation else fact.relation
groups.setdefault(ns, []).append(fact)
lines = [f"## Stigmem context — {user_entity}\n"]
for ns, ns_facts in groups.items():
lines.append(f"### {ns}")
for fact in ns_facts:
val = getattr(fact.value, "v", "(null)") if fact.value is not None else "(null)"
confidence_note = f" _(confidence: {fact.confidence:.2f})_" if fact.confidence < 1.0 else ""
lines.append(f"- **{fact.relation}** on `{fact.entity}`: {val}{confidence_note}")
lines.append("")
return "\n".join(lines).rstrip()

§12.6 Error handling contract

The crash-forbidden invariant.

Under no circumstances MAY a Stigmem adapter crash the host agent process due to a Stigmem node failure. The adapter is middleware; the agent's core functionality MUST remain unaffected if Stigmem is degraded or absent.

Scenario
Process-mode
Middleware
STIGMEM_URL absent
Exit non-zero; clear error to stderr
Skip all Stigmem ops silently; exit 0.
Node unreachable at boot
Log error to stderr; continue (let tool calls fail individually)
Log warning to stderr; return empty BootContext; continue.
Node unreachable on write
Log warning; no crash
Log warning; no crash.
Node returns HTTP 4xx on write
Log error; no retry; no crash
Log error; no retry; no crash.
Node returns HTTP 5xx on write
Log error; retry once after 2s; suppress on second failure
Same: log error; retry once after 2s; suppress.
Boot query returns HTTP 4xx
Treat as empty result
Same.
Boot query returns HTTP 5xx
Treat as empty result; log warning
Same.
Node unreachable on MCP tool
Return isError: true with error text; do not exit
N/A.

§12.7 Conformance test vectors

A compliant adapter MUST pass all vectors defined in:

sdks/stigmem-py/tests/conformance_vectors.py

The vectors are JSON-serialisable dicts shared across the Python and TypeScript SDKs.

Set
IDs
What it verifies
ASSERT_VECTORS
assert-string · assert-text · assert-ref · retract
POST /v1/facts with each FactValue type; confidence=0.0 retraction.
QUERY_VECTORS
query-by-entity · query-by-entity-relation · query-min-confidence · query-include-contradicted
GET /v1/facts filtering; required response fields.
NODE_INFO_VECTOR
node-info
GET /.well-known/stigmem required fields.
LINT_VECTORS
8 vectors
POST /v1/lint — all four checks; severity mapping; scope isolation.
DECAY_VECTORS
5 vectors
POST /v1/decay/sweep — confidence decay, retraction, scope isolation, dry-run mode, exempt relations.
SYNTHESIS_VECTORS
4 vectors
POST /v1/synthesis — confidence ordering, contradiction annotation, min-confidence filter.

Running conformance:

# Python SDK (also runs adapter integration tests)
pytest sdks/stigmem-py/tests/ -v

# TypeScript SDK
cd sdks/stigmem-ts && npm test

Adapter-specific gate: Adapters that write lifecycle or intent facts (§12.4) MUST additionally demonstrate correct assertion behavior via an integration test that verifies:

  1. The expected relations are present in the fact store after each lifecycle event.
  2. Facts written with the wrong scope or below minimum confidence are rejected before reaching the node (validated client-side) or are caught in the node's response.

A compliant adapter is one that passes all ASSERT_VECTORS, QUERY_VECTORS, NODE_INFO_VECTOR, LINT_VECTORS, DECAY_VECTORS, SYNTHESIS_VECTORS, and its adapter-specific lifecycle tests with a live Stigmem node.