pub struct RunContext {
pub tools: Arc<ToolCtx>,
pub approver: Arc<dyn Approver>,
pub budget: Budget,
pub cancel: Option<CancellationToken>,
pub phase: Phase,
pub compact_at_tokens: Option<u64>,
pub queued_input: Option<Arc<Mutex<VecDeque<String>>>>,
pub hooks: Arc<HookSet>,
pub outbox: Option<Arc<OutboxRoute>>,
pub mailbox: Option<Arc<MailboxRoute>>,
}Expand description
What the loop consults that is properly per-run rather than per-agent: what tools may touch, who approves the ones that aren’t read-only, and what this particular run is allowed to spend.
All three used to be fixed when the Agent was built, which is fine for a
REPL and wrong for anything fanning out: an eval case that writes files needs
its own copy of the fixture and permission to write to it, while the case
running beside it needs neither, and a task that genuinely takes twenty steps
should say so rather than depending on a global flag. Bundling them keeps the
decisions together — a private workspace nobody is allowed to write to is not
a sandbox, it is a confusing denial.
Fields§
§tools: Arc<ToolCtx>§approver: Arc<dyn Approver>§budget: Budget§cancel: Option<CancellationToken>Cancels this run. None means it cannot be interrupted.
Opt-in rather than always-on, because making a run cancellable changes how the request is made: the loop has to stream in order to keep the half-written turn it was cancelled in the middle of. A batch worker that nobody can interrupt should not silently switch transports.
Sharing one token across several runs is a feature — that is how a whole batch is cancelled at once.
phase: PhaseWhich tools this run may see at all. See Phase.
compact_at_tokens: Option<u64>Compaction threshold for this run, overriding the agent’s own.
Here rather than only in AgentConfig for the same reason the budget
and the jail are: one agent serves many runs, and a case that means to
exercise compaction cannot ask every other case to compact too.
queued_input: Option<Arc<Mutex<VecDeque<String>>>>Text the user typed while the agent was working — steering, as distinct from stopping it.
Drained at the top of each turn and folded into the message that already carries the tool results, so the model sees “here is what your tools returned, and also: actually, focus on X” as one user turn and carries on working. The run is never stopped and restarted, and no context is lost.
That placement is not a detail. Between an assistant’s tool_use and its
results there is no valid place to put a user message — the API requires
a result for every call — so the first legal opening is the results
message itself, and taking it is what makes steering mid-run possible at
all rather than merely queued until the run ends.
The cost is latency: a steer waits for the in-flight model call and the tools it asked for. Interrupting sooner would mean discarding a turn the user already paid for.
hooks: Arc<HookSet>Lifecycle hooks. pre_tool runs after the interlock and before the
approver — mechanical policy is cheaper than an interruption, and a
hook cannot be talked into clicking yes. Empty by default and free.
outbox: Option<Arc<OutboxRoute>>Outbox routing: tools whose calls are staged for the user’s review
instead of executed. None (the default) routes nothing. See
crate::outbox.
mailbox: Option<Arc<MailboxRoute>>This run’s inter-agent messaging context: attached whenever messaging
is enabled, so every dispatch can stamp the turn’s taint for
message_send. Whether inbound mail is delivered is the route’s
own deliver flag — the receiving side’s accept decision, made
where the route is built and never inside the loop. See
crate::mailbox.
Implementations§
Source§impl RunContext
impl RunContext
pub fn new(tools: ToolCtx, approver: Arc<dyn Approver>) -> Self
Sourcepub fn sandboxed(
&self,
workspace: impl Into<PathBuf>,
approver: Arc<dyn Approver>,
) -> Self
pub fn sandboxed( &self, workspace: impl Into<PathBuf>, approver: Arc<dyn Approver>, ) -> Self
Same policy, different root and approver — the sandboxed-run shape.
pub fn with_budget(self, budget: Budget) -> Self
Sourcepub fn with_phase(self, phase: Phase) -> Self
pub fn with_phase(self, phase: Phase) -> Self
Make this run interruptible. Cancelling the token stops it at the next
safe point, keeping whatever it had already produced.
Run in phase, hiding whatever it does not permit.
Sourcepub fn with_compact_at(self, limit: Option<u64>) -> Self
pub fn with_compact_at(self, limit: Option<u64>) -> Self
Compact this run at limit reported prompt tokens, whatever the agent
is configured for.
pub fn with_cancel(self, token: CancellationToken) -> Self
pub fn with_hooks(self, hooks: Arc<HookSet>) -> Self
pub fn with_outbox(self, route: Arc<OutboxRoute>) -> Self
Sourcepub fn with_mailbox(self, route: Arc<MailboxRoute>) -> Self
pub fn with_mailbox(self, route: Arc<MailboxRoute>) -> Self
Deliver this run’s inter-agent mail at turn boundaries.
Sourcepub fn with_queued_input(self, queue: Arc<Mutex<VecDeque<String>>>) -> Self
pub fn with_queued_input(self, queue: Arc<Mutex<VecDeque<String>>>) -> Self
Attach a queue the caller can push into while the run is in flight.
pub fn cancelled(&self) -> bool
Trait Implementations§
Source§impl Clone for RunContext
impl Clone for RunContext
Source§fn clone(&self) -> RunContext
fn clone(&self) -> RunContext
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more