Wardrik.Agent (wardrik_protocol v0.1.0-rc.1)

Copy Markdown

An agent, and the operations on one.

Wardrik.Agent.ask(scope, "acme/triage", "What's on fire?")
#=> {:ok, %Wardrik.Message{id: "msg_Xq3f...", cursor: "eyJhY21lL3RyaWFnZSI6NDF9"}}

Wardrik.Agent.read(scope, "acme/triage")
#=> {:ok, %Wardrik.Agent{id: "acme/triage", status: :running, node: "wardrik@box1", pending: 0, ...}}

Fields

  • :id - the agent's ID, as "acme/triage".
  • :name - its name.
  • :status - :idle, :running, :parked or :asleep.
  • :node - the node it runs on.
  • :pending - how many messages wait behind the current one.
  • :next_run - when it next runs.
  • :spent_today - what it has spent today.
  • :activity - what it's doing now. See Wardrik.Activity.
  • :interrupts - the calls it waits on a person for. See Wardrik.Interrupt.
  • :cursor - where its event log stands.

Agents from Wardrik.Agents.list/2 leave out :activity, :interrupts and :cursor.

Summary

Functions

Approve a call an agent waits on

Send an agent a message

Read where a person authorizes a call

List the tool calls an agent is running

Stop what an agent is doing

Empty an agent's conversation

Approve or reject the calls an agent waits on

Read an agent's definition

Reject a call an agent waits on

Read an agent's log

Builds one from the protocol's JSON.

Builds an agent from one item of the agents.list output.

Move an agent to another node

Read what an agent is doing now

Sends the agent a message and returns its answer once the run ends.

Read what an agent's runs did and cost

Sends the agent a message and streams the text of its answer.

Read an agent's log, then follow new events as they arrive. Returns {:ok, stream} of {%Wardrik.Event{}, cursor} pairs.

Read an agent's conversation as a person reads it

Returns it as the protocol's JSON, without fields that are nil.

Remove one of an agent's triggers

Set one of an agent's triggers

Types

t()

@type t() :: %Wardrik.Agent{
  activity: term(),
  cursor: term(),
  id: term(),
  interrupts: term(),
  name: term(),
  next_run: term(),
  node: term(),
  pending: term(),
  spent_today: term(),
  status: term()
}

Functions

approve(scope, agent, interrupt, input \\ [])

@spec approve(Wardrik.Scope.t(), String.t() | struct(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Approve a call an agent waits on

agent.decide with one approval. Recorded as the caller's.

POST /v1/agents/{agent}/interrupts/{interrupt}/approve

ask(scope, agent, input \\ [])

@spec ask(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Send an agent a message

POST /v1/agents/{agent}/messages

authorization(scope, agent, interrupt, input \\ [])

@spec authorization(
  Wardrik.Scope.t(),
  String.t() | struct(),
  String.t() | struct(),
  term()
) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Read where a person authorizes a call

GET /v1/agents/{agent}/interrupts/{interrupt}/authorization

calls(scope, agent, input \\ [])

@spec calls(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

List the tool calls an agent is running

Answers not_found while the agent sleeps.

GET /v1/agents/{agent}/calls

cancel(scope, agent, input \\ [])

@spec cancel(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Stop what an agent is doing

POST /v1/agents/{agent}/cancel

clear(scope, agent, input \\ [])

@spec clear(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Empty an agent's conversation

Answers conflict while it runs a turn or waits on a person.

DELETE /v1/agents/{agent}/conversation

decide(scope, agent, input \\ [])

@spec decide(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Approve or reject the calls an agent waits on

The decisions are taken together and recorded as the caller's. A rejection's reason is what the model is told in place of the call's answer. An approval's note is what it reads beside the answer.

POST /v1/agents/{agent}/decisions

define(scope, agent, input \\ [])

@spec define(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Define an agent

Starts the agent the definition describes, or brings the one running to it from its next turn. A definition put again replaces the last. A key nothing here supports yet answers not_supported, naming it.

PUT /v1/agents/{agent}

definition(scope, agent, input \\ [])

@spec definition(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Read an agent's definition

GET /v1/agents/{agent}/definition

deny(scope, agent, interrupt, input \\ [])

@spec deny(Wardrik.Scope.t(), String.t() | struct(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Reject a call an agent waits on

agent.decide with one rejection. Recorded as the caller's.

POST /v1/agents/{agent}/interrupts/{interrupt}/deny

events(scope, agent, input \\ [])

@spec events(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Read an agent's log

GET /v1/agents/{agent}/events

forget(scope, agent, input \\ [])

@spec forget(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Forget an agent

DELETE /v1/agents/{agent}

from_json(json)

@spec from_json(map()) :: t()

Builds one from the protocol's JSON.

from_summary(summary)

@spec from_summary(map()) :: t()

Builds an agent from one item of the agents.list output.

kill(scope, agent, call, input \\ [])

@spec kill(Wardrik.Scope.t(), String.t() | struct(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Stop one tool call

DELETE /v1/agents/{agent}/calls/{call}

move(scope, agent, input \\ [])

@spec move(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Move an agent to another node

Starts the agent again on node, as it was. A turn it's taking ends, and what it waits on is abandoned, so ask it again once it's moved.

POST /v1/agents/{agent}/move

read(scope, agent, input \\ [])

@spec read(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Read what an agent is doing now

GET /v1/agents/{agent}

reply(scope, agent, input, opts \\ [])

@spec reply(Wardrik.Scope.t(), String.t() | t(), term(), keyword()) ::
  {:ok, Wardrik.Reply.t()}
  | {:waiting, [Wardrik.Interrupt.t()]}
  | {:error, Wardrik.Error.t()}

Sends the agent a message and returns its answer once the run ends.

Wardrik.Agent.reply(scope, "acme/triage", "What's on fire?")
#=> {:ok, %Wardrik.Reply{message: "msg_Xq3f...", run: "0af76519...", text: "Nothing's on fire."}}

Returns {:waiting, interrupts} if the run waits on a person. Returns {:error, %Wardrik.Error{}} if the agent can't be reached or the run fails. Takes the :timeout option of stream/4.

runs(scope, agent, input \\ [])

@spec runs(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Read what an agent's runs did and cost

GET /v1/agents/{agent}/runs

spawn(scope, agent, input \\ [])

@spec spawn(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Start an agent

POST /v1/agents/{agent}/spawn

stop(scope, agent, input \\ [])

@spec stop(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Stop an agent

POST /v1/agents/{agent}/stop

stream(scope, agent, input, opts \\ [])

@spec stream(Wardrik.Scope.t(), String.t() | t(), term(), keyword()) ::
  Enumerable.t() | {:ok, reference()}

Sends the agent a message and streams the text of its answer.

scope |> Wardrik.Agent.stream("acme/triage", "What's on fire?") |> Enum.each(&IO.write/1)

The stream ends when the run ends, including when it fails. Use reply/4 to see how it ended. Raises Wardrik.Error if the agent can't be reached.

With to: pid, returns {:ok, ref} and sends pid each item as {Wardrik, ref, item}:

  1. {:text, chunk}, any number of times.
  2. One of {:done, %Wardrik.Reply{}}, {:waiting, interrupts} or {:failed, why}.

Options

  • :to - a pid to send the answer to, in place of returning a stream.
  • :timeout - milliseconds to wait for each part of the answer. Ten minutes unless set.

stream_events(scope, agent, input \\ [])

@spec stream_events(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  {:ok, Enumerable.t()} | :ok | {:error, Wardrik.Error.t()}

Read an agent's log, then follow new events as they arrive. Returns {:ok, stream} of {%Wardrik.Event{}, cursor} pairs.

GET /v1/agents/{agent}/events

timeline(scope, agent, input \\ [])

@spec timeline(Wardrik.Scope.t(), String.t() | struct(), term()) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Read an agent's conversation as a person reads it

GET /v1/agents/{agent}/timeline

to_json(value)

@spec to_json(t()) :: map()

Returns it as the protocol's JSON, without fields that are nil.

trigger_remove(scope, agent, trigger, input \\ [])

@spec trigger_remove(
  Wardrik.Scope.t(),
  String.t() | struct(),
  String.t() | struct(),
  term()
) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Remove one of an agent's triggers

DELETE /v1/agents/{agent}/triggers/{trigger}

trigger_set(scope, agent, trigger, input \\ [])

@spec trigger_set(
  Wardrik.Scope.t(),
  String.t() | struct(),
  String.t() | struct(),
  term()
) ::
  term() | :ok | {:error, Wardrik.Error.t()}

Set one of an agent's triggers

Sets or changes one trigger of an agent with a definition, which keeps it; not_found where it has none. A trigger whose every and timezone stay keeps its next run.

PUT /v1/agents/{agent}/triggers/{trigger}