WardrikProtocol
Copy MarkdownWardrik's wire format: its events as CloudEvents, and its operations as
one OpenAPI document. It also holds the typed Elixir
functions, like Wardrik.Agent.ask/3, that packages built on Wardrik call.
Install
def deps do
[
{:wardrik_protocol, "~> 0.1.0-rc.1"}
]
endThe schemas
Each schema is a JSON file in priv/v1. Its $id is urn:wardrik:schema:v1:<file name>.
| File | Describes |
|---|---|
<noun>.<verb>.json | the data of the event wardrik.<noun>.<verb>, like run.started.json |
cloudevent.json | the envelope every event is sent in |
defs.json | types events share, like message, principal and activity |
openapi.json | every operation, and its HTTP route |
| any other | an operation's input or output, like ask.json and agent_snapshot.json |
Live events are sent as they happen and never stored. Their schemas set "x-wardrik-live": true:
activity.changed, message.delta, reasoning.delta, subagent.progress and
tool_call.progress.
Check an event
WardrikProtocol.schema/1 returns a schema with every $ref inlined, so any JSON Schema validator
can use it without a resolver. With JSV:
envelope = JSV.build!(WardrikProtocol.schema("cloudevent"))
data = JSV.build!(WardrikProtocol.schema("run.started"))
{:ok, _event} = JSV.validate(event, envelope)
{:ok, _data} = JSV.validate(event["data"], data)WardrikProtocol.types/0 lists every event type. WardrikProtocol.dataschema/1 returns the
dataschema for a type.
The operations
openapi.json defines each operation once, by its operationId, like agent.ask. The HTTP API,
the CLI and agents' tools all use the same IDs. Any OpenAPI 3.1 tool can read the file, so SDKs
are generated from it.
Each operation carries three extensions next to its HTTP route:
| Extension | Meaning | Example |
|---|---|---|
x-wardrik-action | what the caller must be allowed to do | agent.ask |
x-wardrik-effect | read, change or destructive | read |
x-wardrik-subject | what it acts on | agent, agents, deployment |
WardrikProtocol.operations/0 lists them as maps. WardrikProtocol.operation/1 finds one by ID.
Each has a single input schema that merges its path parameters, query parameters and body, so
surfaces other than HTTP see one set of named fields:
%{input: input, output: output} = WardrikProtocol.operation("agent.ask")
{:ok, _input} = JSV.validate(%{"agent" => "acme/triage", "content" => "Hi"}, JSV.build!(input))parameters lists which fields go in the HTTP path or query. The rest go in the body.