pig/agent/runtime
Sans-IO runtime interpreter for the pig agent.
The runtime is an OTP actor that:
- Receives prompts (Run) or control messages (Stop)
- Calls
update.update(state, msg)— pure state machine - For each effect, applies hooks then executes
- Produces SessionEvent values and sends to dispatcher
- Feeds effect results back as new AgentMsg values
The core logic (update.gleam) is pure. This module is all IO.
Types
The action to take only after a pending commit succeeds.
pub type PostCommitDisposition {
ResumeFromHistory
ReturnMessage(message.Message)
ReturnAiError(error.AiError)
}
Constructors
-
ResumeFromHistory -
ReturnMessage(message.Message) -
ReturnAiError(error.AiError)
Configuration for the runtime. Holds everything the runtime needs that the pure core doesn’t — provider function, tool registry, hooks, dispatcher, and model name.
pub type RuntimeConfig {
RuntimeConfig(
provider: fn(
List(message.Message),
List(tool_definition.ToolDefinition),
) -> Result(inference.InferenceResult, error.AiError),
tools: tool.ToolRegistry,
hooks: List(hooks.Hooks),
dispatcher: process.Subject(dispatcher.DispatcherMessage),
model: String,
max_iterations: Int,
)
}
Constructors
-
RuntimeConfig( provider: fn( List(message.Message), List(tool_definition.ToolDefinition), ) -> Result(inference.InferenceResult, error.AiError), tools: tool.ToolRegistry, hooks: List(hooks.Hooks), dispatcher: process.Subject(dispatcher.DispatcherMessage), model: String, max_iterations: Int, )
Messages the runtime actor can receive.
pub type RuntimeMsg {
Run(
prompt: String,
reply_to: process.Subject(
Result(message.Message, run_error.RunError),
),
)
Continue(
reply_to: process.Subject(
Result(message.Message, run_error.RunError),
),
)
GetHistory(reply_to: process.Subject(List(message.Message)))
Stop
}
Constructors
-
Run( prompt: String, reply_to: process.Subject( Result(message.Message, run_error.RunError), ), )Run a prompt and reply with the result.
-
Continue( reply_to: process.Subject( Result(message.Message, run_error.RunError), ), )Resume the agent loop from its current history.
-
GetHistory(reply_to: process.Subject(List(message.Message)))Get the agent’s current message history.
-
StopStop the actor.
Internal state held by the runtime actor.
pub type RuntimeState {
RuntimeState(
agent_state: state.AgentState,
config: RuntimeConfig,
session: SessionState,
)
}
Constructors
-
RuntimeState( agent_state: state.AgentState, config: RuntimeConfig, session: SessionState, )
Durable session state held by the runtime.
pub type SessionState {
SessionDisabled
SessionReady(
store: session_store.SessionStore,
head: option.Option(String),
)
SessionPending(
store: session_store.SessionStore,
commit: session_store.SessionCommit,
candidate: state.AgentState,
disposition: PostCommitDisposition,
)
}
Constructors
-
SessionDisabledNo synchronous durable transcript is configured.
-
SessionReady( store: session_store.SessionStore, head: option.Option(String), )Commits are written to
storeagainst the currenthead. -
SessionPending( store: session_store.SessionStore, commit: session_store.SessionCommit, candidate: state.AgentState, disposition: PostCommitDisposition, )A commit failed ambiguously and must be retried unchanged before new work.
Values
pub fn history(
subject: process.Subject(RuntimeMsg),
timeout: Int,
) -> List(message.Message)
Get the agent’s current message history.
pub fn run(
subject: process.Subject(RuntimeMsg),
prompt: String,
timeout: Int,
) -> Result(message.Message, run_error.RunError)
Send a prompt to the runtime and wait for a response.
pub fn run_continue(
subject: process.Subject(RuntimeMsg),
timeout: Int,
) -> Result(message.Message, run_error.RunError)
Resume the agent loop from its current history.
Looks at the last message in history to determine the entry point:
- User/Tool message → call the provider
- Assistant with stop_reason=ToolUse → execute pending tool calls
- Assistant with stop_reason=Stop → return immediately
- Assistant with stop_reason=Length/Error → re-call provider
pub fn start(
config: RuntimeConfig,
) -> Result(process.Subject(RuntimeMsg), actor.StartError)
Start the runtime actor with the given configuration.
pub fn start_with_state(
config: RuntimeConfig,
initial_state: RuntimeState,
) -> Result(process.Subject(RuntimeMsg), actor.StartError)
Start the runtime actor with a pre-built state.
Used by pig.gleam when session replay needs to happen before start.
pub fn stop(subject: process.Subject(RuntimeMsg)) -> Nil
Send a stop message to the runtime actor.
pub fn supervised(
agent_config: state.AgentConfig,
dispatcher_name: process.Name(dispatcher.DispatcherMessage),
name: process.Name(RuntimeMsg),
initial_history: List(message.Message),
session: SessionState,
) -> supervision.ChildSpecification(Nil)
Create a ChildSpecification for a named runtime actor.
initial_history becomes current before the actor starts, and session
carries the durable commit head associated with it. The Subject can be
recovered after supervisor start with process.named_subject(name).
pub fn supervised_with_session_store(
agent_config: state.AgentConfig,
dispatcher_name: process.Name(dispatcher.DispatcherMessage),
name: process.Name(RuntimeMsg),
store: session_store.SessionStore,
) -> supervision.ChildSpecification(Nil)
Create a durable ChildSpecification which reloads the session on every start.
A load failure during a later OTP restart is reported as actor initialisation failure, allowing the supervisor to apply its usual restart policy.
pub fn try_run(
subject: process.Subject(RuntimeMsg),
prompt: String,
timeout: Int,
) -> Result(Result(message.Message, run_error.RunError), Nil)
Send a prompt to the runtime and wait for a response.
Returns Error(Nil) if the call times out or the runtime crashes.
pub fn try_run_continue(
subject: process.Subject(RuntimeMsg),
timeout: Int,
) -> Result(Result(message.Message, run_error.RunError), Nil)
Resume the agent loop from its current history and wait for a response.
Returns Error(Nil) if the call times out or the runtime crashes.