tool_context
Shared context object passed to tools that need platform access.
Tools opt-in to receiving context by declaring a ctx parameter in
their run() signature. The ToolRegistry inspects the
handler at call-time and injects the context automatically – the LLM
never sees or fills this parameter.
- class tool_context.ToolCallRecord(record_id=<factory>, tool_name='', raw_arguments_json='', result_output='', success=True, execution_start=0.0, execution_end=0.0, duration_ms=0.0, order_index=0, round_number=0, turn_summary_id='')[source]
Bases:
objectOne tool call’s full execution trace.
Stored as a hidden Redis message after each inference turn so the agent can retrieve exact inputs/outputs on demand via the
retrieve_tool_call_logtool.- Parameters:
- class tool_context.ToolContext(platform='', channel_id='', user_id='', user_name='', guild_id='', adapter=None, message_id='', config=None, redis=None, message_cache=None, kg_manager=None, task_manager=None, threadweave=None, tool_registry=None, conversation_manager=None, openrouter=None, all_adapters=<factory>, adapters_by_name=<factory>, disclosed_skill_ids=<factory>, injected_tools=None, injected_tools_session=<factory>, sent_files=<factory>, sent_rich_messages=<factory>, tools_executed=<factory>, observability_request_id='', room_context=None, tool_call_records=<factory>, persona_pref_manager=None, visual_memory=None)[source]
Bases:
objectRuntime context injected into tool handlers that opt in to it.
A single mutable bag of per-message state and shared service handles that the tool-execution layer hands to any tool whose
run()declares actxparameter. It exists so tools can reach platform adapters, Redis, the knowledge graph, the conversation/message caches, the live OpenRouterClient, and sibling managers without importing them directly (which would create circular imports) and without the LLM ever seeing these fields — the registry inspects the handler signature and injects this object behind the model’s back.Beyond carrying read-only handles, several fields are write-back channels: tool handlers append to
injected_tools,sent_files,sent_rich_messages, andtools_executedduring a round, andOpenRouterClient.chat()reads/clears them between rounds to merge newly injected tools and to surface media the bot emitted. Because parallel tools in one model round share the same instance and run underasyncio.gather, these mutations must stay append-only/atomic. Instances are constructed by the message-processing paths that drive tool calls — e.g.message_processor/generate_and_send.py,message_processor/channel_heartbeat.py,core/outbound_consumer.py, andkg_agentic_extraction.py— and by the swarm/test harnesses.The individual fields are documented by their per-attribute docstrings below.
- Parameters:
platform (str)
channel_id (str)
user_id (str)
user_name (str)
guild_id (str)
adapter (PlatformAdapter | None)
message_id (str)
config (Config | None)
redis (Any)
message_cache (MessageCache | None)
kg_manager (KnowledgeGraphManager | None)
task_manager (TaskManager | None)
threadweave (ThreadweaveManager | None)
tool_registry (ToolRegistry | None)
conversation_manager (ConversationManager | None)
openrouter (Any)
observability_request_id (str)
tool_call_records (list[ToolCallRecord])
persona_pref_manager (Any)
visual_memory (Any)
- adapter: PlatformAdapter | None = None
The
PlatformAdapterinstance for the originating platform.For Discord this is a
DiscordPlatformwhose.clientproperty exposes the underlyingdiscord.Client.
- config: Config | None = None
Global bot
Config. Gives tools access toredis_url,model, and other settings.
- redis: Any = None
Shared async Redis client (
redis.asyncio.Redis).Nonewhen Redis is not configured. Tools should guard access with anif ctx.redis is not Nonecheck.
- message_cache: MessageCache | None = None
Shared
MessageCacheinstance for retrieving cached messages asCachedMessageobjects.Nonewhen Redis is not configured.
- kg_manager: KnowledgeGraphManager | None = None
Shared
KnowledgeGraphManagerfor the knowledge graph system.Nonewhen Redis is not configured.
- task_manager: TaskManager | None = None
Shared
TaskManagerfor checking background task results. Injected by the message processor so tools likecheck_taskcan access it.
- threadweave: ThreadweaveManager | None = None
Shared
ThreadweaveManagerfor the Threadweave persistent knowledge system (DNA Vault, Persistent Weave, Shadow Memory).Nonewhen Redis is not configured.
- tool_registry: ToolRegistry | None = None
The live
ToolRegistrythat holds all loaded tools.Allows meta-tools like
list_all_toolsandreload_toolsto inspect or modify the running tool set.
- conversation_manager: ConversationManager | None = None
Shared
ConversationManagerfor per-channel conversation histories.Allows tools to read or manipulate the in-memory context window for any channel.
- openrouter: Any = None
The
OpenRouterClientinstance for the current session.Used for shared HTTP/registry access. Effective tool-round limits for the active
chat()call are scoped viacontextvars(seeget_tool_round_limit_box());extend_tool_loopmutates that per-invocation state, notopenrouterfields.
- all_adapters: list[Any]
All running
PlatformAdapterinstances.Allows cross-platform tools (e.g.
list_active_servers) to query every connected platform, not just the one that triggered the current message.
- adapters_by_name: dict[str, Any]
All platform adapters keyed by name (e.g.
"discord","discord-self","matrix").Allows tools to look up a specific adapter directly:
selfbot = ctx.adapters_by_name.get("discord-self")
- disclosed_skill_ids: list[str]
Agent Skill ids disclosed in tier-1 catalog for this message (for
activate_skill).
- injected_tools: list[str] | None = None
Per-round staging list for
request_tool_injection.Tool handlers append here; after each tool round
OpenRouterClient.chat()merges these names into the livetool_nameslist passed to the LLM and then clears this field. Each round starts withinjected_tools = []so parallel tools in one round share one list safely.The model keeps seeing merged tools on every later round of the same
chat()call because the client extends the in-memorytool_nameslist — not because this attribute stays populated.When several tools run in the same model round they share this
ToolContextand execute concurrently viaasyncio.gather. Preferlist.extend/append; avoid non-atomic read-modify-write patterns. Backgrounded tools (task manager) may still race with later rounds on the samectx—keep mutations minimal.
- injected_tools_session: list[str]
All tool names merged via injection during the current
chat()loop.Appended when the client merges
injected_toolsintotool_names; cleared at the start ofchat()whenrecord_executed_toolsis true (same astools_executed). Use this to introspect which extra tools stayed active for the whole generation.
- sent_files: list[dict[str, Any]]
Media files sent to the channel during tool execution.
Each entry has keys:
data(rawbytes),filename(str),mimetype(str), and optionallyfile_url(str). After the LLM call, the message processor converts these into real multimodal content parts (image_url,input_audio, etc.) viamedia_to_content_parts()and appends them to conversation history so the bot can see its own visual and audio outputs on subsequent turns.Parallel tools in one LLM round share this list; appends are safe, but do not assume ordering of entries matches tool-call order unless you serialize tool execution.
- sent_rich_messages: list[dict[str, Any]]
Rich Discord messages sent during tool execution.
Each entry has keys:
text(serialized LLM-visible content) and optionallymessage_id. The message processor appends these to assistant history/cache so embed-only sends remain visible later.
- tools_executed: list[str]
Tool names executed during the current top-level
OpenRouterClient.chat()loop, in first-seen order (each name at most once).Populated by the client when
record_executed_toolsis true; cleared at the start of each such call. Nestedchat()calls (e.g. subagents) should passrecord_executed_tools=Falseto avoid polluting this list.
- observability_request_id: str = ''
Correlation id for one user message → LLM → reply (Redis observability).
- room_context: dict[str, Any] | None = None
Prompt
room_contextfor the active channel (when built).Used by tools that need parity with the main system prompt, e.g. swarm subagent rendering of
dominant_emotions/narrative_tone.
- tool_call_records: list[ToolCallRecord]
Per-turn tool call execution traces.
Populated by
OpenRouterClient.chat()after each tool round completes (post-gather barrier). Consumed byrun_generate_and_send()to write hidden Redis messages and theStargazer-System-Logsummary. Cleared at the start of eachchat()call whenrecord_executed_toolsis true.
- persona_pref_manager: Any = None
Shared
PersonaPreferenceManagerfor the persona preference memory system.Allows persona preference tools (record, review, evolve, retract) to access the manager without a circular import.
Nonewhen the feature is disabled or Redis is not configured.
- visual_memory: Any = None
Shared
VisualMemoryEnginefor the visual pattern recognition memory system.Allows visual memory tools (repost_image, label_visual_entity) to access the engine for image retrieval and entity management.
Nonewhen visual memory is disabled or not initialized.