Run agents
Copy MarkdownSetup
Paste this into IEx, with your Anthropic key:
Mix.install([{:wardrik_core, "~> 0.1.0-rc.2"}])
System.put_env("ANTHROPIC_API_KEY", "sk-ant-...")
children = [
{WardrikCore.Backends.MemoryStore, name: :agents},
{WardrikCore, backend: {WardrikCore.Backends.MemoryStore, name: :agents}}
]
{:ok, _} = Supervisor.start_link(children, strategy: :rest_for_one)In an app, put the two children in your supervision tree.
Start an agent
{:ok, agent} = WardrikCore.start_agent(agent_id: "support", model: "anthropic:claude-haiku-4-5")
:ok = WardrikCore.ask(agent, "What's on fire?")
WardrikCore.history(agent)
#=> [#Message<:user text>, #Message<:assistant text>]ask/3returns once the message is stored. The agent answers in its own process.- Agent IDs are your app's. Wardrik doesn't read them.
Conversations
A conversation runs on the agent's options, with its own history:
{:ok, thread} =
WardrikCore.start_agent(
agent_id: "support",
conversation: "C1",
model: "anthropic:claude-haiku-4-5"
)
WardrikCore.whereis("support")
WardrikCore.whereis({"support", "C1"})"support" alone means the agent's main history, {"support", nil}.
Where agents are kept
| Backend | Keeps agents | Needs |
|---|---|---|
WardrikCore.Backends.MemoryStore | In memory, until the node stops | Nothing |
EKVStore | On disk, on each node | {:ekv, "~> 0.4"} |
ObjectStore | In an S3-compatible bucket | Bucket and credentials |
MirrorStore | In two backends, while you migrate | The two backends |
The last three are under DurableServer.Backends.
On disk:
children = [
{EKV, name: :agents, data_dir: "/var/lib/my_app/agents", cluster_size: 1},
{WardrikCore, backend: {DurableServer.Backends.EKVStore, name: :agents}}
]In S3:
children = [
{WardrikCore,
backend:
{DurableServer.Backends.ObjectStore,
bucket: "my-app-agents",
access_key_id: System.fetch_env!("AWS_ACCESS_KEY_ID"),
secret_access_key: System.fetch_env!("AWS_SECRET_ACCESS_KEY"),
s3_endpoint: "https://s3.amazonaws.com",
default_region: "us-east-1"}}
]To keep agents in Postgres, use WardrikStore.Durable from
wardrik_store.
After a crash
- An agent that crashes restarts and picks its message back up.
- With a backend that keeps agents, so does one whose node died. A sweep finds it every
:discovery_interval_ms(60_000by default). - A turn resumes from its last checkpoint, without calling the model again.
- A lost tool call runs again if its tool is
read_onlyoridempotent. Otherwise it parks as:in_doubt:
{:tool_calls, [{call, {:park, :in_doubt}}]} = WardrikCore.parked(agent)
# Run it again
WardrikCore.resume(agent, %{call.id => :approve})
# Or tell the model it didn't run
WardrikCore.resume(agent, %{call.id => {:deny, "It may have run already."}})Options
start_agent/2 takes :instructions, :capabilities, :middleware, :principal,
:credentials, :keys, :events, :metadata, :timeout, :max_rounds, :retries and
:prices. See WardrikCore.start_agent/2.
configure/2 changes them from the next turn:
:ok =
WardrikCore.configure(agent,
instructions: "Answer in one sentence.",
prices: %{"anthropic:claude-haiku-4-5" => [input: 1.0, output: 5.0]}
)Control a running agent
| Function | Does |
|---|---|
ask/3 | Queues a message. A running turn ends at its next step |
interrupt/1 | Stops the running or parked turn |
kill/2 | Stops one running tool call. The model gets an error |
resume/3 | Resumes a parked turn |
status/1, history/1, parked/1 | What the agent is doing, has said, and waits on |
stop/1 | Stops the agent until it's started again |
delete/2 | Stops the agent and deletes it |
list/1, whereis/2 | Every saved agent, and the running process for one |
nodes/1, placements/1, move/3 | Cluster nodes, where each agent runs, and moving one |
WardrikCore.status(agent)
#=> :idle
WardrikCore.list()
#=> [{"support", nil}, {"support", "C1"}]
:ok = WardrikCore.delete({"support", "C1"})