WardrikProtocol

Wardrik's wire format: events as CloudEvents, operations as one OpenAPI document, and typed Elixir functions like Wardrik.Agent.ask/4.

Install

def deps do
  [
    {:wardrik_protocol, "~> 0.1.0-rc.6"}
  ]
end

Check an event

WardrikProtocol.schema/1 inlines every $ref, so any JSON Schema validator can use it. With JSV, in a fresh IEx session:

Mix.install([{:wardrik_protocol, "~> 0.1.0-rc.6"}, {:jsv, "~> 0.26"}])

event = %{
  "specversion" => "1.0",
  "id" => "019a3c40-0000-7000-8000-000000000001",
  "source" => "wardrik://local/agents/agt_1",
  "type" => "wardrik.run.started",
  "subject" => "runs/run_1",
  "time" => "2026-11-06T12:00:00Z",
  "datacontenttype" => "application/json",
  "dataschema" => "urn:wardrik:schema:v1:run.started",
  "traceparent" => "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01",
  "data" => %{"run" => %{"id" => "0af7651916cd43dd8448eb211c80319c", "message_ids" => ["msg_1"]}}
}

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)

Look up an operation

%{path: path, conversation: route, input: input} = WardrikProtocol.operation("agent.ask")
path
# => "/v1/agents/{agent}/messages"

route
# => "/v1/agents/{agent}/conversations/{conversation}/messages"

{:ok, _input} = JSV.validate(%{"agent" => "agt_1", "content" => "Hi"}, JSV.build!(input))

Call an operation

Create a scope with your running Wardrik runtime:

scope = MyApp.AgentRuntime.as("maria")
Wardrik.Agent.ask(scope, "agt_1", "Hi", conversation: "C1")
Wardrik.Agent.approve(scope, agent: "agt_1", interrupt: "call_1", conversation: "C1")