WardrikCore (wardrik_core v0.1.0-rc.3)
Copy MarkdownA durable agent runtime. Agents survive a crash, wait for a person, and run every call through your code.
children = [
{WardrikCore.Backends.MemoryStore, name: :agents},
{WardrikCore, backend: {WardrikCore.Backends.MemoryStore, name: :agents}}
]
Supervisor.start_link(children, strategy: :rest_for_one)
{:ok, agent} =
WardrikCore.start_agent(agent_id: "triage", model: "anthropic:claude-haiku-4-5")
:ok = WardrikCore.ask(agent, "What's on fire?")
WardrikCore.history(agent)- An agent runs one turn at a time. Tools come from
WardrikCore.Capabilitymodules. - Every model call and tool call runs through
WardrikCore.Middleware. - To run more than one instance, give each child a
:name, and pass it asinstance.
See the Run agents guide.
Summary
Types
An agent's id and its conversation's, nil for the agent's own history.
A model's price in US dollars per million tokens.
Functions
Queues a message. Returns once it's stored. A running turn ends at its next step.
Runs agents under your supervision tree.
Changes an agent's model or settings, from its next turn.
Returns model's context window in tokens, from the model catalog, or nil.
Stops the agent and deletes its saved state. Returns :ok if there's no such agent.
Asks an evaluation :model the :questions about :state, from inside a turn.
Calls the context's model once, from inside a turn, through the middleware.
Returns the agent's conversation.
Stops the running or parked turn. Returns {:error, :idle} if there's none.
Stops the running tool call call_id. The model gets an error, and the turn goes on.
Returns the key of every saved agent.
Restarts the agent on the node :to, ending its turn.
Returns the names of the cluster nodes agents run on, sorted.
Returns what the agent waits on, or nil.
Returns each saved agent's key mapped to the node running it, or nil if it isn't running.
Returns model's price from the model catalog, in US dollars per million tokens, or nil.
Resumes a parked turn, passing input to whatever parked it.
Starts an agent, or loads it if it was saved before.
Returns what the agent is doing: :idle, :running, :waiting on resume/3, or :due to
run a turn.
Stops the agent. It stays saved, and runs again when started.
Runs prompt as one turn of a subagent, from inside a tool or middleware.
Returns the running agent, or nil.
Types
An agent's id, for its own history, or a key/0 for one of its conversations.
An agent's id and its conversation's, nil for the agent's own history.
A model's price in US dollars per million tokens.
Functions
@spec ask(GenServer.server(), String.t(), map()) :: :ok
Queues a message. Returns once it's stored. A running turn ends at its next step.
:ok = WardrikCore.ask(agent, "Open an issue for the login bug.", %{principal: maria})Metadata
:principal- theWardrikCore.Principalwho asked. The turn acts for them.:id- the message's ID. Generated by default.
Runs agents under your supervision tree.
{WardrikCore, backend: {WardrikCore.Backends.MemoryStore, name: :agents}}Options
:backend- required. The durable_server backend agents are saved in.:name- the instance's name.WardrikCoreby default.
Other options go to DurableServer.Supervisor.
@spec configure(GenServer.server(), keyword()) :: :ok
Changes an agent's model or settings, from its next turn.
Takes :model and the options of start_agent/2, except :agent_id and :conversation.
@spec context_window(LLMDB.Model.t() | String.t()) :: pos_integer() | nil
Returns model's context window in tokens, from the model catalog, or nil.
Stops the agent and deletes its saved state. Returns :ok if there's no such agent.
@spec evaluate(WardrikCore.Context.t(), model: String.t(), state: String.t() | map(), questions: map() ) :: {:ok, map(), %{required(atom()) => number()}} | {:error, term()}
Asks an evaluation :model the :questions about :state, from inside a turn.
questions = %{"urgent" => %{type: :boolean, instructions: "Is this urgent?"}}
{:ok, %{"urgent" => %{"probability" => p}}, measurements} =
WardrikCore.evaluate(context,
model: "typesafe:jev-latest",
state: "The site is down.",
questions: questions
)
context = WardrikCore.Context.measure(context, measurements)Returns each answer by question name, and what the call used.
@spec generate(WardrikCore.Context.t()) :: WardrikCore.Middleware.result()
Calls the context's model once, from inside a turn, through the middleware.
summarizing = %{context | instructions: "Summarise this conversation.", tools: []}
{:ok, summarized} = WardrikCore.generate(summarizing)
ReqLLM.Response.text(summarized.response)
#=> "The user asked about..."Returns the context with response set and the reply added to messages. Streams nothing.
@spec history(GenServer.server()) :: [ReqLLM.Message.t()]
Returns the agent's conversation.
@spec interrupt(GenServer.server()) :: :ok | {:error, :idle}
Stops the running or parked turn. Returns {:error, :idle} if there's none.
@spec kill(GenServer.server(), String.t()) :: :ok | {:error, :not_running}
Stops the running tool call call_id. The model gets an error, and the turn goes on.
Returns the key of every saved agent.
Restarts the agent on the node :to, ending its turn.
WardrikCore.move("triage", to: "wardrik@10.0.0.2")Returns {:error, :no_such_node} or {:error, :not_found}.
Returns the names of the cluster nodes agents run on, sorted.
@spec parked(GenServer.server()) :: term() | nil
Returns what the agent waits on, or nil.
Parked tool calls return {:tool_calls, [{call, outcome}]}.
Returns each saved agent's key mapped to the node running it, or nil if it isn't running.
@spec price(LLMDB.Model.t() | String.t()) :: price() | nil
Returns model's price from the model catalog, in US dollars per million tokens, or nil.
WardrikCore.price("anthropic:claude-haiku-4-5")
#=> [input: 1.0, output: 5.0, cache_read: 0.1, cache_write: 1.25]
@spec resume(GenServer.server(), term(), map()) :: :ok | {:error, :not_parked}
Resumes a parked turn, passing input to whatever parked it.
WardrikCore.resume(agent, %{"call_1" => :approve}, %{by: maria})- Answer parked tool calls by ID, one at a time or together.
metadatais yours. It appears on the turn's[:wardrik_core, :turn, :start]event.- Returns
{:error, :not_parked}if the agent isn't waiting.
Starts an agent, or loads it if it was saved before.
{:ok, agent} =
WardrikCore.start_agent(
agent_id: "support",
model: "anthropic:claude-haiku-4-5",
instructions: "Answer customers' questions about their orders.",
capabilities: [{MyApp.Orders, []}]
)Options
:agent_id- required. Your ID for the agent.:model- required. A model spec, as"anthropic:claude-haiku-4-5".:conversation- your ID for one of the agent's conversations, with its own history.nil, the main history, by default.:instructions- the system prompt. Never kept in the history.:capabilities- modules that give the agent its tools. SeeWardrikCore.Capability.:middleware- wraps every step. SeeWardrikCore.Middleware.:principal- who the agent acts as. SeeWardrikCore.Principal.:credentials- where tools find a person's tokens. SeeWardrikCore.Credentials.:keys- where code finds API keys. SeeWardrikCore.Keys.:events- where events go. SeeWardrikCore.Events.:metadata- your own data, passed to middleware.%{}by default.:timeout- how long a turn may take, in milliseconds.:infinityby default.:max_rounds- model calls per turn, or:infinity.25by default.:retries- seeWardrikCore.Retry.:model_timeouts- how long a model call waits, asReqLLMtakes them. Agents run unattended and a model may think for minutes, so a call waits up to five minutes for an answer, and as long on a stream gone quiet:[receive_timeout: 300_000, stream_idle_timeout: 300_000]by default. A turn's:timeoutbounds the whole.:prices- US dollars per million tokens, by model spec, over the model catalog's.%{}by default.prices: %{"zai_coding_plan:glm-5.1" => [input: 1.54, output: 4.84]}
@spec status(GenServer.server()) :: :idle | :running | :waiting | :due
Returns what the agent is doing: :idle, :running, :waiting on resume/3, or :due to
run a turn.
@spec stop(GenServer.server()) :: :ok
Stops the agent. It stays saved, and runs again when started.
@spec subagent(WardrikCore.Context.t(), String.t(), keyword()) :: {:ok, %{text: String.t(), labels: [String.t()]}, map()} | {:error, term(), map()}
Runs prompt as one turn of a subagent, from inside a tool or middleware.
{:ok, %{text: text, labels: labels}, measurements} =
WardrikCore.subagent(context, "Find this week's releases.", name: "researcher")- Uses the caller's model, middleware and tools.
- Returns
{:error, reason, measurements}if it fails. Pass the measurements toWardrikCore.Context.measure/2. - It can't wait for a person. A call that would park fails it.
- It emits
[:wardrik_core, :subagent, _]events in place of its own steps'. SeeWardrikCore.Telemetry.
Options
:name-"subagent"by default. Set as the context'ssubagentwhile it runs.:instructions,:capabilities,:max_rounds- replace the caller's.:except_tools- tool names to leave out.[]by default.:timeout- milliseconds before it fails with:timeout.:infinityby default.
Returns the running agent, or nil.
WardrikCore.whereis("support")
WardrikCore.whereis({"support", "C1"})