pub struct AgentContext {Show 32 fields
pub agent_id: String,
pub config: Arc<AgentConfig>,
pub broker: AnyBroker,
pub sessions: Arc<SessionManager>,
pub memory: Option<Arc<LongTermMemory>>,
pub router: Option<Arc<AgentRouter>>,
pub peers: Option<Arc<PeerDirectory>>,
pub mcp: Option<Arc<SessionMcpRuntime>>,
pub session_id: Option<Uuid>,
pub effective: Option<Arc<EffectiveBindingPolicy>>,
pub effective_tools: Option<Arc<ToolRegistry>>,
pub credentials: Option<Arc<AgentCredentialResolver>>,
pub breakers: Option<Arc<BreakerRegistry>>,
pub redactor: Option<Arc<Redactor>>,
pub transcripts_index: Option<Arc<TranscriptsIndex>>,
pub link_extractor: Option<Arc<LinkExtractor>>,
pub context_optimization: Option<ResolvedContextOptimization>,
pub event_emitter: Option<Arc<dyn AgentEventEmitter>>,
pub dispatch: Option<Arc<DispatchToolContext>>,
pub repl_registry: Option<Arc<ReplRegistry>>,
pub sender_trusted: bool,
pub inbound_origin: Option<(String, String, String)>,
pub plan_mode: Arc<RwLock<PlanModeState>>,
pub plan_approval_registry: Arc<PlanApprovalRegistry>,
pub todos: Arc<RwLock<TodoList>>,
pub team_id: Option<String>,
pub team_member_name: Option<String>,
pub inbox: Arc<RwLock<Vec<DmMessage>>>,
pub proactive_enabled: bool,
pub binding_role: Option<String>,
pub binding: Option<BindingContext>,
pub inbound: Option<InboundMessageMeta>,
/* private fields */
}Fields§
§agent_id: String§config: Arc<AgentConfig>§broker: AnyBroker§sessions: Arc<SessionManager>§memory: Option<Arc<LongTermMemory>>§router: Option<Arc<AgentRouter>>§peers: Option<Arc<PeerDirectory>>Snapshot of peer agents running in this process. Feeds the
auto-generated # PEERS system-prompt block so the LLM knows
which ids to pass to delegate(...). None in test/bootstrap
contexts where peer discovery doesn’t apply.
mcp: Option<Arc<SessionMcpRuntime>>MCP runtime scoped to this session (if MCP is enabled).
session_id: Option<Uuid>Active session id when the context is built inside an LLM turn. None for contexts built outside the loop (heartbeat bootstrap, tests). Used by tool handlers that opt into context passthrough.
effective: Option<Arc<EffectiveBindingPolicy>>Per-binding capability snapshot resolved at intake. Some when the
runtime matched the inbound event to an InboundBinding for this
agent; None for paths without a binding match (delegation
receive, heartbeat, tests). Use AgentContext::effective_policy
to access a policy that always has a value — it synthesises one
from the agent-level config when effective is None.
effective_tools: Option<Arc<ToolRegistry>>Per-binding tool registry — shares handlers with the agent’s base
registry but only exposes tools that survive the binding’s
allowed_tools filter. None on code paths without a binding
match (delegation receive, heartbeat, tests); consumers fall
back to the behavior’s base registry in that case.
credentials: Option<Arc<AgentCredentialResolver>>Resolver that maps this agent’s id to the opaque credential
handles it is allowed to use for outbound traffic.
None in early-boot / test contexts; consumers must treat that
as “no credentials configured” (tools return an unbound error
rather than publishing from an arbitrary account).
breakers: Option<Arc<BreakerRegistry>>Per-(channel, instance) breaker registry shared by
plugin outbound tools. None for runtimes without credentials.
redactor: Option<Arc<Redactor>>Pre-persistence redactor for transcript content. None in
test/bootstrap contexts → behavior keeps content untouched.
transcripts_index: Option<Arc<TranscriptsIndex>>FTS5 index over transcript content. None when the subsystem
is disabled or initialization failed; consumers fall back to
JSONL-only persistence + substring scan.
link_extractor: Option<Arc<LinkExtractor>>Shared link extractor (HTTP client + LRU cache).
None in early-boot / test contexts; llm_behavior treats
that as “link understanding disabled regardless of config”.
context_optimization: Option<ResolvedContextOptimization>Current effective enables for the four context-optimization
mechanisms (hot-reloadable). Set per-event by
AgentRuntime from RuntimeSnapshot::context_optimization, so
a config reload that flips a flag is observed on the next
turn without restarting the behavior. None for legacy /
test contexts that haven’t been wired through the snapshot —
in that case llm_behavior falls back to the boot-time
prompt_cache_enabled / compaction_runtime.enabled flags.
event_emitter: Option<Arc<dyn AgentEventEmitter>>Agent event emitter threaded from the
AgentRuntime so llm_behavior can attach it to
per-turn TranscriptWriter instances. Without this,
transcript appends emit through the default
NoopAgentEventEmitter and never reach the bootstrap’s
broadcast firehose, leaving subscribers (microapps with
agent_events_subscribe_all) silent on live updates.
None for test/bootstrap contexts; consumers fall back
to no-op emission in that case.
dispatch: Option<Arc<DispatchToolContext>>Bundle of services consumed by the dispatch tool
handlers (program_phase, list_agents, etc.). Populated at
boot when the project tracker is enabled. None keeps the
dispatch tools off — handlers return a friendly error so
the LLM doesn’t pretend they worked.
repl_registry: Option<Arc<ReplRegistry>>REPL session registry. Some when repl-tool
feature is enabled AND the binding config has repl.enabled.
Holds persistent Python/Node/bash subprocesses.
sender_trusted: boolSender’s pairing-trust bit, set by intake after the
pairing gate runs. Defaults to false so any path that
forgets to thread it through fails closed under
require_trusted=true. Read-only tools bypass this gate.
inbound_origin: Option<(String, String, String)>(plugin, instance, sender_id) of the inbound event
that produced this turn, when the runtime matched a binding.
Lets the dispatch handler synthesise an OriginChannel for
program_phase so notify_origin lands back in the chat.
plan_mode: Arc<RwLock<PlanModeState>>Plan-mode state for this goal. Shared across the
dispatcher (read on every tool call) and the EnterPlanMode /
ExitPlanMode tools (write). SQLite is canonical (column on
agent_registry.goals.plan_mode); this is a hot cache. New
contexts default to Off; the runtime hydrates the value from
the registry at goal spawn / reattach.
plan_approval_registry: Arc<PlanApprovalRegistry>Process-shared registry of pending plan-mode approvals.
EnterPlanMode does not touch it; ExitPlanMode
installs a waiter when plan_mode.require_approval is on; the
plan_mode_resolve operator tool fires the matching waiter.
Tests construct their own registry to avoid cross-test races.
todos: Arc<RwLock<TodoList>>Intra-turn scratch todo list. Owned by the model
(mutated via TodoWrite). Distinct from TaskFlow:
Todo is in-memory + per-goal + flat; TaskFlow is persistent
- cross-session + DAG. Reattach does not restore todos — they die with the goal because re-deriving them mid-turn is cheap and stale items are confusing.
team_id: Option<String>When set, this goal is running as a member of a named team.
The lead’s team_id is its own team’s id; ordinary
sub-agents stay None.
team_member_name: Option<String>Human-readable member name within team_id (e.g.
"researcher"). None ⇔ team_id.is_none().
Some(TEAM_LEAD_NAME) for the lead’s own goal.
inbox: Arc<RwLock<Vec<DmMessage>>>DMs the team router delivered while this goal was running. Consumed at the start of each turn by the prompt-assembly path. Concurrent appends are serialised by the goal’s tokio task scheduler — there is no inner lock because the consume is single-threaded per-goal.
proactive_enabled: boolWhether this goal runs in proactive tick-loop mode.
Set at goal spawn from EffectiveBindingPolicy::proactive().enabled.
Read by llm_behavior to inject the proactive system hint.
binding_role: Option<String>Binding role tag ("coordinator", "worker", "proactive",
or None). Stored here so llm_behavior can inject the coordinator
hint without re-reading the binding config on every turn.
binding: Option<BindingContext>Composed binding context propagated to tool calls via
_meta.nexo.binding. Some when intake matched an
InboundBinding; None for bindingless paths (delegation
receive, heartbeat bootstrap, tests).
Construct via super::binding_context_from_effective(&policy, agent_id, session_id) at the intake site that matches the
binding. Tool dispatch reads this to populate the JSON-RPC
params._meta block.
inbound: Option<InboundMessageMeta>Per-turn metadata about the inbound message
that triggered this agent turn (sender id, msg id,
timestamp, …). Some when the intake site populated it
(whatsapp plugin, event-subscriber binding, webhook
receiver, delegation receive, heartbeat tick, …); None
for legacy producers not yet migrated and for tests.
Surfaces under _meta.nexo.inbound via
AgentContext::build_meta_value.
Implementations§
Source§impl AgentContext
impl AgentContext
pub fn new( agent_id: impl Into<String>, config: Arc<AgentConfig>, broker: AnyBroker, sessions: Arc<SessionManager>, ) -> Self
Sourcepub fn with_team(
self,
team_id: impl Into<String>,
name: impl Into<String>,
) -> Self
pub fn with_team( self, team_id: impl Into<String>, name: impl Into<String>, ) -> Self
Mark this context as running as a teammate.
name is the human-readable handle within the team
("researcher", "tester", or TEAM_LEAD_NAME).
Sourcepub fn is_teammate(&self) -> bool
pub fn is_teammate(&self) -> bool
true when both team_id and
team_member_name are set. The runtime’s
teammate-cannot-spawn-teammate guard inspects this.
Sourcepub fn with_plan_mode(self, state: Arc<RwLock<PlanModeState>>) -> Self
pub fn with_plan_mode(self, state: Arc<RwLock<PlanModeState>>) -> Self
Install a pre-built plan-mode handle. Used at
goal hydration so the runtime can share the same Arc<RwLock>
between the dispatcher (gate) and the registry mirror (write
path).
Sourcepub fn with_plan_approval_registry(
self,
registry: Arc<PlanApprovalRegistry>,
) -> Self
pub fn with_plan_approval_registry( self, registry: Arc<PlanApprovalRegistry>, ) -> Self
Install a process-shared plan-mode approval registry.
Production wiring constructs one per process and
hands it to every AgentContext; tests build their own to
avoid cross-test races.
Sourcepub fn is_interactive(&self) -> bool
pub fn is_interactive(&self) -> bool
true when this goal is rooted in a live channel
that can deliver an operator approval message. Sub-agent goals
(delegations, future TeamCreate workers), cron / poller /
heartbeat-spawned goals, and bootstrap contexts all return
false because they have no inbound channel through which an
operator could approve a plan.
Reference: research/src/acp/session-interaction-mode.ts:4-15
— same intent, “interactive” vs “parent-owned-background”.
pub fn with_sender_trusted(self, v: bool) -> Self
pub fn with_inbound_origin( self, plugin: impl Into<String>, instance: impl Into<String>, sender_id: impl Into<String>, ) -> Self
Sourcepub fn with_inbound_meta(self, meta: InboundMessageMeta) -> Self
pub fn with_inbound_meta(self, meta: InboundMessageMeta) -> Self
Install per-turn InboundMessageMeta on the context.
Producers (channel plugins, event-subscriber,
delegation, heartbeat) build the meta at the intake site and
the per-turn dispatch loop layers it on the cloned context
before invoking tools / hooks.
pub fn with_dispatch(self, d: Arc<DispatchToolContext>) -> Self
Sourcepub fn with_context_optimization(self, co: ResolvedContextOptimization) -> Self
pub fn with_context_optimization(self, co: ResolvedContextOptimization) -> Self
Set the per-turn context-optimization snapshot. Called by the
agent runtime intake after loading the active RuntimeSnapshot,
so a hot-reload that swaps the snapshot is observed without
rebuilding the behavior.
pub fn with_redactor(self, redactor: Arc<Redactor>) -> Self
Sourcepub fn with_event_emitter(self, emitter: Arc<dyn AgentEventEmitter>) -> Self
pub fn with_event_emitter(self, emitter: Arc<dyn AgentEventEmitter>) -> Self
Install the firehose emitter so per-turn
TranscriptWriter instances built in llm_behavior can
chain .with_emitter() and broadcast TranscriptAppended
to subscribers.
pub fn with_transcripts_index(self, index: Arc<TranscriptsIndex>) -> Self
pub fn with_link_extractor(self, ext: Arc<LinkExtractor>) -> Self
pub fn with_memory(self, memory: Arc<LongTermMemory>) -> Self
pub fn with_router(self, router: Arc<AgentRouter>) -> Self
pub fn with_peers(self, peers: Arc<PeerDirectory>) -> Self
pub fn with_mcp(self, mcp: Arc<SessionMcpRuntime>) -> Self
pub fn with_session_id(self, id: Uuid) -> Self
pub fn with_effective(self, effective: Arc<EffectiveBindingPolicy>) -> Self
Sourcepub fn with_mcp_channel_source(self, source: impl Into<String>) -> Self
pub fn with_mcp_channel_source(self, source: impl Into<String>) -> Self
Layer the MCP channel source on top of the BindingContext
after with_effective has run. No-op if binding is None
(paths without a binding match cannot have an
MCP-channel source — the source rides alongside an
already-matched binding, not as a substitute).
pub fn with_effective_tools(self, tools: Arc<ToolRegistry>) -> Self
Sourcepub fn with_event_source(self, meta: EventSourceMeta) -> Self
pub fn with_event_source(self, meta: EventSourceMeta) -> Self
Populate binding.event_source when the inbound was
synthesised from a NATS event subscriber.
No-op when self.binding is None; logged at debug level
so the call-site can stay branchless if the caller doesn’t
want to gate the call. Caller is expected to gate at the
call site for hot paths (every native-channel inbound
passing through the resolver).
pub fn with_credentials(self, credentials: Arc<AgentCredentialResolver>) -> Self
pub fn with_breakers(self, breakers: Arc<BreakerRegistry>) -> Self
Sourcepub fn effective_policy(&self) -> Arc<EffectiveBindingPolicy> ⓘ
pub fn effective_policy(&self) -> Arc<EffectiveBindingPolicy> ⓘ
Returns the active effective policy, synthesising one from the
agent-level config when no binding was matched. Cheap to call in
hot paths: returns an existing Arc when available and builds a
fresh one only for unbound contexts.
Sourcepub fn build_meta_value(&self) -> Value
pub fn build_meta_value(&self) -> Value
Single source of truth for the _meta payload exposed to
extension tools (stdio JSON-RPC) and MCP tools (tools/call
params._meta). Both surfaces must emit identical wire
shapes so a microapp speaks the same dialect regardless of
which transport delivered the call.
Returned value is a JSON object with two layers:
- flat
agent_id+session_idfor backward-compat with older consumers, - nested
nexo.bindingcarryingBindingContextwhen the intake matched a binding (omitted otherwise to keep the wire compact for delegation receive / heartbeat bootstrap / tests).
Trait Implementations§
Source§impl Clone for AgentContext
impl Clone for AgentContext
Source§fn clone(&self) -> AgentContext
fn clone(&self) -> AgentContext
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for AgentContext
impl !UnwindSafe for AgentContext
impl Freeze for AgentContext
impl Send for AgentContext
impl Sync for AgentContext
impl Unpin for AgentContext
impl UnsafeUnpin for AgentContext
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more