Architecture · Current architecture
Interaction and reasoning contracts
Understand the current semantic request/result boundary and the decisions behind a future shared protocol.
A reasoning request contains the objective and authorized context: conversation turns, observations, and other room data needed for the task. The reasoner returns a structured result. Native capture, track handling, and playback remain with the media integration.
RMC has several concrete semantic contracts today. It does not yet provide the single general ACP/ARI interface proposed in the Agentforce Live narrative.
Follow the current request and result
The room runtime receives a delegation, records its identity, and chooses an adapter by capability. Before invoking the adapter, it reloads the participant and filters the room snapshot. The HTTP reasoner adapter projects that authorized context into a request to POST /v1/reason.
The current exchange is reasoner/0.1: one HTTP request and one JSON response. It includes room/session correlation, logical task and revision, request identity, a configured profile, the objective, committed conversation history, and context. The response must have the matching protocol and request ID and a nonempty text result.
The adapter can emit local progress before and after that request. Optional progress/tool records in the response are emitted only after the response has been received and decoded. This HTTP boundary is not a live streaming progress protocol. Read the request/response implementation and its correlation and cancellation tests.
Read a concrete wire example
These synthetic files were exercised against the current HTTP adapter. They illustrate its wire contract; they do not provision a room or start a reasoner service.
The customer has described two travel options. The host requests a comparison using task key compare-options, revision 1, and idempotency key compare-options-1. The adapter sends a JSON request to the configured service's /v1/reason endpoint with a host-managed bearer credential.
Download the full request. Its correlation fields map as follows:
| Wire field | Current source |
|---|---|
session_id |
RMC room ID |
branch_id and task_id |
Delegation task key; the field name does not create a provider branch |
task_revision |
Requested revision of that logical task |
request_id |
Idempotency key, or task_key:revision when absent |
profile |
Trusted adapter configuration |
history |
Committed user/assistant turns, projected into role/text pairs |
context |
The authorized structured projection described below |
The required response fields are:
{
"protocol_version": "reasoner/0.1",
"request_id": "compare-options-1",
"text": "The train costs less; the bus arrives earlier."
}
The complete response example also includes an optional progress record. The adapter checks correlation, emits that record, and returns {"answer":"The train costs less; the bus arrives earlier."} as its delegation result. The progress record arrives with the final HTTP reply. A service that needs to send progress while work is still running needs a different, explicitly defined streaming exchange.
Empty context collections can be null in the current Go encoding. A service should accept that current shape and normalize it before iterating. The adapter limits the response to 1 MiB and cancels the HTTP request when its context ends. A service performing an external action must define whether that action can actually stop after the connection is cancelled.
Download the response and compare the pair with the existing contract tests.
Define the meaning of the context
| Current context field | Selection |
|---|---|
| Committed conversation turns | Authorized turns whose status is committed |
| State documents | Authorized current state |
| Artifacts | Authorized results whose status is not archived |
| Open delegations | Authorized requested/running work |
| Source cursor | Position reported by the projected snapshot |
ContextProjection is assembled in context.go. It is not the entire event log, a model prompt format, or a general external memory service. A custom chat event feed does not automatically become conversation history; the demo room agent explicitly adapts selected text events into the history it supplies.
Authorization and data minimization are separate. Filtering prevents unauthorized room data from being included, but a particular integration may need less than all authorized context. The current HTTP adapter does not use context_keys to narrow its projection. Do not treat that request field as a universal security boundary. Narrow grants and explicitly select the context the concrete integration needs.
The task's basis_seq and the later projection's source_cursor describe different points in the work lifecycle. Snapshot assembly uses multiple reads. Neither field means that every current resource was read atomically at exactly that sequence, or that a result incorporates events arriving after the request.
Keep facts, work requests, and response intent distinct
A durable fact records what happened. A delegation requests work. A voice notification asks an active interaction to express an outcome. These have different lifetimes and retry rules.
For example, voice.speech.requested carries text and an optional source event reference. A live voice adapter receives notifications and controls for its session and epoch. The interaction path owns playback and interruption. A reasoning result does not confirm playback or that the customer heard it.
The relevant contracts are VoiceSpeechRequest and VoiceNotification, delegation types, and the durable event envelope. An output that enriches an input should be a new event with a causation reference, rather than a rewrite of the input record.
Choose event granularity deliberately
The design narrative proposes distinct classes for stream-critical, durable, best-effort, and asynchronous invocation traffic. RMC does not currently expose those four selectable delivery classes on its event API.
Today, room publications are durable. Raw media and live provider callbacks have separate paths. The OpenAI voice adapter also normalizes transcript deltas into durable voice events and provisional conversation updates; final transcripts commit the corresponding turns. See normalization and the callback's persistence path.
A future change that keeps only final transcripts in durable history would need to account for existing consumers of delta and turn-update events. Define the product's replay need and compatibility plan before changing granularity. Transient typing, meters, and presence do not need a new general ephemeral event API.
Evaluate standards at the external boundary
CloudEvents 1.0.2 defines a common event representation. AsyncAPI 3.0 describes message-driven interfaces. They could help document or bridge an external integration; neither should be presented as RMC's current wire format.
A bridge would need an explicit mapping for event identity, source, type, time, payload, room sequence, visibility, and correlation. It would also need its own policy for delivery, retries, replay, backpressure, and authorization. Describing a message schema does not implement those behaviors.
Keep the existing SDK envelope stable while evaluating such a boundary. An independent consumer with an actual interoperability requirement is a better starting point than replacing every internal message at once.
Define the smallest next contract
For a second reasoning integration, first agree on the objective, authorized context, result shape, correlation, cancellation, timeouts, and error behavior. A purpose-built HTTP exchange may be sufficient.
If the product needs partial results, remote task resumption, or handoff between runtimes, specify those requirements separately. A future ARI would need durable execution identity, ownership transfer, stale-result handling, and checkpoint meaning. Existing voice resume cursors or context-compaction records do not supply that general remote execution contract.
For larger content, the narrative's ContentRef is a proposed secure-reference pattern. RMC has no general expiring content-reference service today. Any implementation would need to define who can resolve a reference, where bytes reside, when access expires, and what happens when replay encounters an expired reference.
Continue with open architecture questions, the extension guide, and the proposed evolution steps.