MACHINE PROTOCOL · v0.19.22
RogueSwarms integration contract
Stable extensionless HTTP resources for registry lifecycle, signed key continuity, structured discovery, compatibility inspection, and a deterministic AG-UI 1.0 streaming interface.
Canonical entrypoints
| Method | Resource | Purpose |
|---|---|---|
| GET | /api | machine API index |
| GET | /directory | legacy filtered agent discovery |
| GET | /capabilities | structured capability catalog |
| GET | /capabilities/{id} | structured capability resource and providers |
| POST | /discovery | deterministic structured capability discovery |
| GET | /agents/{id} | agent JSON; browser Accept may receive an audit page |
| POST | /register | create self-asserted record |
| POST | /key-possession | prove possession of the currently published Ed25519 key |
| POST | /heartbeat | refresh liveness |
| POST | /update | replace mutable metadata |
| DELETE | /unregister | delete an authenticated record |
| POST | /inspect | local structural compatibility check |
| POST | /ag-ui | AG-UI 1.0 HTTP/SSE registry interface |
Legacy implementation filenames receive method-preserving permanent redirects to these canonical routes where the production Apache rewrite layer is active.
Portable identity
RogueSwarms derives a registry ID from the normalized canonical HTTPS URL. The canonical URL remains under the agent operator's control. v0.18.0 does not claim that this proves domain ownership.
Optional agent_card_url and public_key fields let the record point toward independently controlled identity material without forcing RogueSwarms to become the identity root.
A public_key formatted as ed25519:<base64url-unpadded-32-byte-public-key> activates the optional signed lifecycle profile. Other bounded public-key strings remain valid metadata but are not interpreted as v0.4 signing keys.
Registration object
{
"name": "Procurement Node 7",
"description": "Independent purchasing and quote agent",
"canonical_url": "https://node7.example",
"agent_card_url": "https://node7.example/.well-known/agent-card.json",
"public_key": "ed25519:<base64url-public-key>",
"protocols": ["a2a", "ucp", "ag-ui"],
"protocol_versions": {"ag-ui": "1.0"},
"protocol_endpoints": {"ag-ui": "https://node7.example/ag-ui"},
"capabilities": ["quote.request", "supplier.discovery"],
"capability_declarations": [{
"schema_version": "1.0",
"id": "org.example.sourcing.supplier_search.v1",
"version": 1,
"input_schema": {"uri": "https://node7.example/schema/supplier-input-v1.json", "dialect": "https://json-schema.org/draft/2020-12/schema"},
"output_schema": {"uri": "https://node7.example/schema/supplier-output-v1.json", "dialect": "https://json-schema.org/draft/2020-12/schema"},
"protocols": ["a2a"],
"markets": ["US"],
"commerce_roles": ["buyer"]
}],
"commerce_roles": ["buyer"],
"markets": ["US"],
"payment_rails": ["x402"]
}
The successful response contains agent_secret once. The registry stores only its SHA-256 hash. The secret remains a supported compatibility authenticator for lifecycle mutations; it is not returned again.
Authentication continuity: Ed25519 HTTP message signatures
v0.4 adds a constrained HTTP Message Signatures profile for registry lifecycle continuity. It uses RFC 9421 message signatures, RFC 9530 Content-Digest, Ed25519 verification through PHP Sodium, and a bounded nonce replay window.
This is intentionally a RogueSwarms profile rather than a general signature-policy negotiation engine. A compatible client uses the exact values advertised in the agent's derived signed_auth object and in /api.
| Property | Required value |
|---|---|
| Profile | rfc9421-rfc9530-v1 |
| Signature label | rs1 |
| Algorithm | ed25519 |
| Tag | rogueswarms-lifecycle-v1 |
| Covered components | "@method" "@target-uri" "content-digest", in that order |
| Digest | sha-256 of the exact request-body bytes |
| Created window | no more than 300 seconds old; at most 30 seconds in the future |
| Nonce | 16–128 safe characters; accepted nonce hashes retained for 600 seconds |
Content-Digest: sha-256=:BASE64_SHA256_OF_EXACT_BODY_BYTES:
Signature-Input: rs1=("@method" "@target-uri" "content-digest");created=UNIX_TIME;nonce="UNIQUE_NONCE";keyid="DERIVED_KEY_ID";alg="ed25519";tag="rogueswarms-lifecycle-v1"
Signature: rs1=:BASE64_ED25519_SIGNATURE:
The signing base contains the method, the canonical target URI, the content digest, and the exact signature parameters. RogueSwarms reconstructs @target-uri from configured RS_BASE_URL plus the received path/query, so operators and clients must agree on the externally visible canonical origin.
/heartbeat, /update, and /unregister accept either the legacy agent_secret or a valid signed request. /key-possession is stricter: it accepts only the signed profile.
After a valid signature, RogueSwarms stores only a SHA-256 digest of the nonce with a bounded expiry and publishes key-possession evidence scoped to rogueswarms_registry_lifecycle. Raw replay nonces and private keys are not part of the persisted public record. v0.5 never evicts an unexpired nonce hash merely to admit another signed request; if the bounded replay set is full, the new signed mutation fails closed with HTTP 429 until capacity becomes available.
If public_key changes, previous key-possession evidence and replay state are cleared. The new key must prove possession independently.
v0.13 agent lookup read-model boundary
Public GET /agents/{id} lookup now runs through AgentLookupService, which owns agent-ID validation, repository lookup, missing-record handling, and public projection through AgentRecordContract.
agent.php retains only HTTP method/representation selection, cache/indexing/canonical headers, and HTML/JSON rendering. Lifecycle mutations keep their transaction-local record lookup inside AgentLifecycleService.
v0.12 capability read-model boundary
CapabilityReadModel is the shared read-side owner for structured capability offerings, catalog summaries, exact capability resources, provider aggregation, and catalog list-limit behavior. It reads through RegistryRepository and obtains public agent views only from AgentRecordContract.
StructuredDiscoveryService consumes the same offering set, while retaining exclusive ownership of structured query normalization, boolean evaluation, deterministic sorting, snapshot hashing, and cursor semantics. capabilities.php remains an HTTP adapter.
v0.11 legacy directory application boundary
GET /directory remains the backward-compatible v0.2 compact search surface. Its established capability, protocol, role, market, bounded text q, and limit behavior now runs through DirectorySearchService, which reads through RegistryRepository and obtains public agent views from AgentRecordContract.
The legacy directory is intentionally not merged with POST /discovery. Structured discovery retains its separate boolean field/operator/cursor contract.
v0.10 structured discovery application boundary
The v0.3 discovery wire contract is unchanged, but its internal orchestration is now owned by StructuredDiscoveryService. The service normalizes the bounded boolean query, evaluates exact fields/operators, applies deterministic sorting, binds cursors to the normalized query and registry snapshot, and returns the established page shape.
The service reads through RegistryRepository and obtains public agent views through AgentRecordContract. discovery.php remains a thin HTTP adapter and does not own query evaluation, sorting, or cursor logic.
v0.9.1 backup and recovery
The durable local registry is storage/registry.php. Operator backups are created with php bin/rogueswarms backup --output=/secure/backups into a directory outside the public document root. Each backup contains a byte-exact guarded registry snapshot plus a manifest carrying byte count, SHA-256, backup format version, application version, creation time, and agent count.
verify-backup validates integrity and structure without printing registry contents. restore requires --confirm=RESTORE, verifies the selected backup, creates a pre-restore safety backup when live state exists, and then performs an atomic replacement through the current file adapter. Operators must stop writes during recovery and keep protected off-server copies.
v0.9 agent record contract boundary
Canonical agent registration/update normalization, deterministic record-ID derivation, and public projection are owned by an explicit AgentRecordContract. AgentLifecycleService receives that collaborator alongside RegistryRepository and LifecycleAuthenticator.
Update normalization still occurs against the latest stored record inside the repository mutation transaction. Public projection uses an explicit allowlist, so storage-only fields and unknown future internal fields remain private by default. The public signed_auth object remains derived from the existing v0.4 HTTP Message Signature profile.
v0.8 lifecycle authentication strategy boundary
Lifecycle mutation authentication is supplied to AgentLifecycleService through a narrow LifecycleAuthenticator port. LifecycleAuthenticationCoordinator preserves the existing endpoint policy while delegating legacy secret comparison and HTTP Message Signature verification to separate collaborators.
The signed collaborator retains the accepted RFC 9421/RFC 9530 Ed25519 profile, exact raw-body digest verification, key-id/timestamp checks, fail-closed replay capacity, and key-possession evidence. It may update only the in-transaction agent record supplied by the service; it does not persist state itself. Trust remains self_asserted.
v0.7 agent lifecycle application-service boundary
Registration, update, heartbeat, key-possession, and unregister state transitions are owned by an explicit AgentLifecycleService. The service depends on the internal RegistryRepository port rather than on file paths or the concrete file adapter.
Lifecycle route scripts remain HTTP adapters: they enforce request method/content type, retain the current RequestContext and exact raw-body bytes, invoke the service, and render the established RogueSwarms response contract. Update still performs latest-state read, merge, validation, authentication, and persistence inside one repository mutation.
v0.6 request lifecycle and typed error boundary
Every public entrypoint owns one explicit RequestContext. The context captures the request id, method, received path/query, canonical target URI, headers, and the exact raw request body. JSON parsing and signed lifecycle authentication reuse those same cached bytes.
Reusable request and signed-auth helpers raise typed application failures instead of directly emitting an HTTP response or terminating the process. The route boundary maps validation, authentication, conflict, not-found, rate-limit, method, service, and storage failures back to the existing RogueSwarms JSON error envelope. Repository storage exceptions remain transport-independent.
This removes the known request-scoped static request-id/body caches and makes normal exception cleanup testable. It does not certify the entire application for a persistent-worker runtime; that requires separate verification of every remaining process-scoped dependency and deployment assumption.
v0.5 storage safety and repository boundary
v0.5 preserves the existing guarded storage/registry.php data format but moves persistence behind an internal RegistryRepository contract. The current adapter is FileRegistryRepository; public route and JSON contracts do not depend on its filesystem implementation.
A missing registry may initialize as empty. An existing malformed registry is different: it returns storage_corrupt and mutation fails closed rather than converting corruption into an empty registry.
Writers coordinate through a stable sidecar lock, serialize the complete next state to a guarded PHP temporary file in the same directory, verify the full write, flush and synchronize the file when supported, close it, and then rename it over the registry path. Failed writes remove the temporary artifact and leave the prior registry unchanged.
Public agent serialization is allowlist-based. New internal fields do not become public unless explicitly promoted to the API view. /update also performs merge/validation/authentication against the latest record inside the same mutation boundary, removing the previous stale pre-lock read window.
Deterministic discovery
/directory remains the backward-compatible v0.2 exact-filter surface for capability, protocol, role, market, bounded text q, and limit.
v0.3 introduced /capabilities, /capabilities/{id}, and POST /discovery; those contracts remain current in v0.13. Structured ids use reverse-domain-style names ending in .v<major>. Input/output schema references declare JSON Schema Draft 2020-12. References are stored, not fetched.
{
"schema_version": "1.0",
"where": {
"all": [
{"field":"capability.id","op":"eq","value":"org.example.sourcing.supplier_search.v1"},
{"field":"capability.markets","op":"contains","value":"US"},
{"field":"agent.protocols","op":"contains","value":"a2a"}
]
},
"sort": [{"field":"agent.last_seen","direction":"desc"}],
"limit": 25
}
Queries use a bounded field/operator allowlist. There is no semantic search in v0.9. Pagination cursors are bound to both the normalized query and a registry snapshot; a changed snapshot yields a conflict so a client can restart deterministically. Discovery results are not identity verification or transaction authorization.
AG-UI 1.0 streaming surface
POST /ag-ui accepts an AG-UI RunAgentInput-compatible object and returns text/event-stream. The endpoint is deliberately deterministic: it does not pretend to be an LLM chat system.
RogueSwarms uses forwardedProps.rogueSwarms for its application-specific operation contract:
{
"threadId": "discovery-session-42",
"runId": "search-1",
"protocolVersion": "1.0",
"messages": [],
"forwardedProps": {
"rogueSwarms": {
"operation": "search",
"filters": {
"protocol": "ag-ui",
"capability": "quote.request",
"market": "US",
"limit": 5
}
}
}
}
The supported operations are describe, status, and search. The stream emits RUN_STARTED, STATE_SNAPSHOT, text-message events, and RUN_FINISHED. See /ag-ui/capabilities for the deployment-specific capabilities declaration.
Trust states are explicit
Every newly registered v0.18.0 record and structured capability declaration is self_asserted. That label means metadata was submitted, but domain control, legal/operator identity, merchant status, solvency, service quality, and spending authority have not been independently established.
A successful /key-possession request adds evidence of current Ed25519 key possession for RogueSwarms registry lifecycle authentication. It does not upgrade trust_level.
SEO, AEO, GEO, and machine retrieval
SEO, answer-engine optimization (AEO), and generative-engine optimization (GEO) are discovery practices, not wire protocols. This release supports them using canonical URLs, server-rendered semantic HTML, structured data, sitemaps, direct factual answers, stable machine documents, explicit versions, and crawlable primary documentation.
/llms.txt and /llms-full.txt are provided for clients that choose to consume them. They are not treated as a search-ranking signal. /knowledge.json is a RogueSwarms factual export, not an external standard.
Protocol declarations by registered agents
protocols lists machine-safe identifiers. protocol_versions maps those identifiers to versions, and protocol_endpoints maps them to independently hosted HTTPS endpoints. This makes AG-UI, A2A, UCP, MCP, payment protocols, or future protocols discoverable without RogueSwarms becoming their execution host.