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.2"}
]
end
Check an event
WardrikProtocol.schema/1 inlines every $ref, so any JSON Schema validator can use it. 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)
- Schemas are in
priv/v1, one JSON file each.run.started.jsonis thedataofwardrik.run.started. WardrikProtocol.types/0lists every event type.- Live events, like
message.delta, are never stored. Their schemas set"x-wardrik-live": true.
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))
openapi.jsonnames each operation by itsoperationId, likeagent.ask. HTTP, the CLI and agents' tools use the same IDs.inputis one schema for the path, query and body together.x-wardrik-actionis what the caller must be allowed to do.x-wardrik-effectisread,changeordestructive.- Agent IDs are your app's: 1 to 255 characters, no control characters. In a route,
{agent}is one URL-encoded segment.
Call an operation
Wardrik.Agent.ask(scope, "agt_1", "Hi", conversation: "C1")
Wardrik.Agent.approve(scope, agent: "agt_1", interrupt: "call_1", conversation: "C1")
- An operation with one path parameter takes it as an argument, and
conversation:inopts. - An operation with two or more takes one keyword list,
conversation:included. So doesWardrik.Agent.decide/2. - An interrupt from
Wardrik.Agent.reply/4orWardrik.Interrupts.list/2names its agent and conversation:Wardrik.Agent.approve(scope, interrupt: interrupt). - An unknown key raises
ArgumentError.