Status: normative implementation contract for runtime transport work.
References:
spec/rpc-edn.allium (canonical wire contract)spec/prompt-slash-commands.allium (backend-owned slash grammar)spec/frontend-action-rpc.allium (backend-requested frontend-native actions)spec/emacs-frontend.allium (frontend consumer expectations)All wire keys are EDN kebab-case keywords.
Required keys: :id :kind :op
Allowed keys: :id :kind :op :params
Constraints:
:kind MUST be :request:id MUST be non-empty string:op MUST be non-empty stringRequired keys: :id :kind :op :ok
Allowed keys: :id :kind :op :ok :data
Constraints:
:kind MUST be :response:ok is booleanRequired keys: :kind :error-code :error-message
Allowed keys: :kind :id :op :error-code :error-message :retryable :data
Constraints:
:kind MUST be :errorRequired keys: :kind :event :data
Allowed keys: :kind :event :data :id :seq :ts
Constraints:
:kind MUST be :event:seq (when present) MUST be monotonic increasing:response | :event | :error).handshake is allowed before ready.{:kind :error :id <req-id?> :op <op?> :error-code "transport/not-ready" ...}:error-code "protocol/unsupported-version"1 and sets transport ready.id -> op.:response or :error with matching :id clears entry.max_pending_requests guard.query_eql request contractCanonical input contract for wire requests:
:params {:query <string>} where <string> parses as EDN vector query.Validation outcomes:
Success response shape:
{:id ... :kind :response :op "query_eql" :ok true :data {:result <query-result>}}Parity expectation:
:psi.graph/* and :psi.memory/* must return values when runtime context provides them.The transport op router MUST remain a thin translation boundary over existing psi.agent-session.core APIs.
| RPC op | Params contract | Runtime mapping target | Success :data shape | Canonical error mapping |
|---|---|---|---|---|
handshake | {:client-info {:name s :version s :protocol-version s :features [s*]?}} | transport-level negotiation (not session domain op) | {:server-info {:protocol-version s :features [s*] :session-id s? :model-id s? :thinking-level s?}} | protocol/unsupported-version, request/invalid-params |
Handshake remains transport-focused. Initial session/UI snapshots are delivered through normal subscribed events rather than a special handshake bootstrap event. context/updated now carries the canonical context snapshot plus backend-projected session-tree widget payload.
Runtime-owned public projection delivery is event-driven:
:projection/context-changed, :projection/ui-changed)query_eql | {:query <edn-string-vector>} | session/query-in | {:result any} | request/invalid-params, request/invalid-query, runtime/query-failed |
| command | {:text s} | backend slash-command dispatch | {:accepted true} | transport/not-ready, request/invalid-params, runtime/failed |
| frontend_action_result | {:request-id s :action-name s :status ("submitted"\|"cancelled"\|"failed") :value ? :error-message s?} | apply/cancel/fail a backend-requested frontend action | {:accepted true} | transport/not-ready, request/invalid-params, runtime/failed |
| prompt | {:message s :images ?} | session/prompt-in! | {:accepted true} | transport/not-ready, request/invalid-params, request/session-not-idle, runtime/failed |
| steer | {:message s :images ?} | session/steer-in! | {:accepted true} | transport/not-ready, request/invalid-params, runtime/failed |
| follow_up | {:message s :images ?} | session/follow-up-in! | {:accepted true} | transport/not-ready, request/invalid-params, runtime/failed |
| abort | {} | session/abort-in! | {:accepted true} | transport/not-ready, runtime/failed |
| login_begin | {:session-id s? :provider s?} | oauth/begin-login! + commands/select-login-provider | {:provider {:id s :name s} :url s :uses-callback-server boolean :pending-login true} | transport/not-ready, request/invalid-params, runtime/failed |
| login_complete | {:input s?} | oauth/complete-login! using transport pending-login state | {:provider {:id s :name s} :logged-in true} | transport/not-ready, request/no-pending-login, request/invalid-params, runtime/failed |
| new_session | {:session-id s? :parent-session ?} | session/new-session-in! | {:session-id s :session-file s?} | transport/not-ready, request/invalid-params, runtime/failed |
| switch_session | {:session-id s? :session-path s} | session/resume-session-in! | {:session-id s :session-file s?} | transport/not-ready, request/invalid-params, request/not-found, runtime/failed |
| fork | {:session-id s? :entry-id s} | session/fork-session-in! | {:session-id s :session-file s?} | transport/not-ready, request/invalid-params, runtime/failed |
| set_session_name | {:name s} | session/set-session-name-in! | {:session-name s} | transport/not-ready, request/invalid-params, runtime/failed |
| set_model | {:provider s :model-id s} | resolve model + session/set-model-in! | {:model {:provider s :id s}} | transport/not-ready, request/invalid-params, request/unknown-model, runtime/failed |
| cycle_model | {:direction ("next"\|"prev")?} | session/cycle-model-in! | {:model {:provider s :id s}} | transport/not-ready, request/invalid-params, runtime/failed |
| set_thinking_level | {:level keyword\|string\|int} | session/set-thinking-level-in! | {:thinking-level any} | transport/not-ready, request/invalid-params, runtime/failed |
| cycle_thinking_level | {} | session/cycle-thinking-level-in! | {:thinking-level any} | transport/not-ready, runtime/failed |
| compact | {:custom-instructions s?} | session/manual-compact-in! | {:compacted true :summary ?} | transport/not-ready, request/session-not-idle, runtime/failed |
| set_auto_compaction | {:enabled boolean} | session/set-auto-compaction-in! | {:enabled boolean} | transport/not-ready, request/invalid-params, runtime/failed |
| set_auto_retry | {:enabled boolean} | session/set-auto-retry-in! | {:enabled boolean} | transport/not-ready, request/invalid-params, runtime/failed |
| get_state | {} | session/query-in (state attrs projection) | {:state map} | transport/not-ready, runtime/query-failed |
| get_messages | {} | session/query-in (messages projection) | {:messages vector} | transport/not-ready, runtime/query-failed |
| get_session_stats | {} | session/diagnostics-in and/or query projection | {:stats map} | transport/not-ready, runtime/query-failed |
| subscribe | {:topics [string*]?} | transport subscription state | {:subscribed [string*]} | transport/not-ready, request/invalid-params |
| unsubscribe | {:topics [string*]?} | transport subscription state | {:subscribed [string*]} | transport/not-ready, request/invalid-params |
| ping | {} | transport heartbeat | {:pong true :protocol-version s} | transport/not-ready |If :op is unknown or not implemented in current runtime:
:kind :error:id echoed when present:op echoed when present:error-code "request/op-not-supported":error-message stable, human-readable:data {:supported-ops [...]}Ops currently expected to start as unsupported until later implementation tasks land:
abort_retrybashabort_bashexport_htmlget_fork_messagesget_last_assistant_textget_commandsget_available_modelsOnly catalog topics from rpc-edn.allium may be emitted:
session/updatedsession/resumedsession/rehydratedassistant/deltaassistant/messagetool/starttool/deltatool/executingtool/updatetool/resultui/dialog-requestedui/frontend-action-requested (:ui/action is the canonical action model; legacy payload duplication removed)ui/widgets-updatedui/status-updatedui/notificationfooter/updatedcommand-resulterrorPlanned source signal exemplars for bridge implementation:
:text-delta, :tool-start, :tool-delta, :tool-executing, :tool-execution-update, :tool-resultsession_switch, resume flows, and subscribed initial snapshot emissionBridge requirements:
:seq + :ts policy supporttransport/not-readytransport/invalid-frametransport/max-pending-exceededprotocol/unsupported-versionprotocol/invalid-enveloperequest/invalid-idrequest/invalid-oprequest/invalid-paramsrequest/invalid-queryrequest/op-not-supportedrequest/session-not-idlerequest/not-foundrequest/unknown-modelruntime/query-failedruntime/failed| Story criterion | Covered by this contract |
|---|---|
| 1. Canonical request validation | Sections 1, 8 |
| 2. Handshake gate + compatibility | Sections 2, 8 |
| 3. Canonical response/error/event envelopes | Section 1 |
| 4. Pending request lifecycle | Section 3 |
| 5. Event stream interleaving | Sections 7, 1 |
| 6. Event topic/payload catalog compliance | Section 7 |
7. query_eql graph/memory parity | Sections 4, 5 |
| 8. stdout discipline | Section 1 (Transport discipline) |
| 9. Tests (contract target) | Sections 1–8 define testable rules |
1.0).rpc-edn.allium catalog.Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |