feat(agent): add MyTool for runtime self-inspection#3177
Conversation
Add a built-in tool that lets the agent inspect and modify its own runtime state (model, iterations, context window, etc.). Key features: - inspect: view current config, usage stats, and subagent status - modify: adjust parameters at runtime (protected by type/range validation) - Subagent observability: inspect running subagent tasks (phase, iteration, tool events, errors) — subagents are no longer a black box - Watchdog corrects out-of-bounds values on each iteration - Enabled by default in read-only mode (self_modify: false) - All changes are in-memory only; restart restores defaults - Comprehensive test suite (90 tests) Includes a self-awareness skill (always-on) with progressive disclosure: SKILL.md for core rules, references/examples.md for detailed scenarios.
Re-bin
left a comment
There was a problem hiding this comment.
This PR introduces a whole new tool, two new config keys, and a dataclass on the subagent side — but the boundary is honest: a small, self-contained feature layered onto infrastructure that already exists on main.
What it actually does. It gives the agent a real view of its own runtime (model, max_iterations, context_window_tokens, _last_usage, subagents, web_config, exec_config) through a my tool with two actions: check (read, dot-paths allowed) and set (bounded writes + an in-memory scratchpad). The subagent side exposes a live SubagentStatus so the main agent is no longer staring into a black box when it spawns work.
Why this is the right shape. The AgentRunSpec.checkpoint_callback and AgentHookContext.tool_events plumbing was already there. This PR just plugs in two consumers — _LoopHook.before_iteration writes _current_iteration, and _SubagentHook.after_iteration snapshots status. Nothing in AgentLoop or SubagentManager gets rearchitected; the new surface is nanobot/agent/tools/self.py and the my skill.
Boundary looks clean. BLOCKED hides the infra that shouldn't be touched (bus, provider, sessions, _mcp_*, channels_config, …). READ_ONLY covers the things you want to inspect but never overwrite (exec_config, web_config, subagents, _current_iteration). _SENSITIVE_NAMES is checked on every segment of the dot-path, so nested secrets can't slip through. RESTRICTED enforces type + range on the three knobs an agent might reasonably want to retune (max_iterations, context_window_tokens, model). Scratchpad is JSON-safe, capped at 64 keys and depth 10, in-memory only — exactly the right ambition for "per-session notes."
Defaults are conservative where it matters: my_set: false. The one thing worth naming out loud is that my_enabled: true does add a tool to every existing user's tool list by default. Because writes are off by default, I think that's fine — but it's a behavior change worth one line in release notes.
Local verification. Merged latest main in (ort, clean). Ran the full suite:
1956 passed in 64.38s
CI is green on 3.11 / 3.12 / 3.13. No open review comments, mergeable_state: clean.
One nit for whoever hits the merge button: the lone commit is still titled feat(agent): add SelfTool … (self_modify: false), while the code and PR body have settled on MyTool / my_enabled / my_set. Squash with the PR title so git log doesn't carry the old naming.
From my side, this is a real feature with a narrow surface area and the defaults are right. Ready to merge.
Summary
Add MyTool — a runtime self-inspection tool that lets the agent check and set its own state (model, iterations, context window, token usage, web/exec config).
my_enabled: true/my_set: falsecheckaction: view any attribute via dot-path; without key shows full config overviewsetaction: change config values with type/range validation, or store notes in scratchpadmy,check/set) designed for LLM comprehensionTest plan
(cherry-picked from #2521)