[BUG] An agent started by $.agent.spawn from a $.clock callback can’t reach its own plugin’s tool.call hook

Status Open
Reported on v2.1.296
Maintainer reply None cached
Activity 0 comments · opened Oct 14, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

A mod registers a tool with $.tool.register and answers it with on('tool.call', { tool: 'mcp__<plugin>__ping' }, ...).
If the mod starts a subagent with $.agent.spawn inside a command.run hook, the subagent calls the tool and the hook answers (pong).

If the same spawn runs from a $.clock.after callback instead, outside any hook, the subagent’s call fails within about 10-150 ms with <plugin> registered the tool ping but no tool.call hook answered this call. The hook never runs: a file write on its first line never happens.

Scope tested

Claude Code 2.1.296 and 2.1.299, on Linux.
Loaded with --plugin-dir, with CLAUDE_CODE_PLUGIN_DIRS, and under --remote-control: same result each time.
An agent the main model starts through the Agent tool reaches the hook fine.

What Should Happen?

a plugin’s tool.call hooks answer calls from every agent in the session, however the agent was started.

Error Messages/Logs

[DEBUG] hooks module timer-spawn-probe@inline tool.call skipped: re-entry (the plugin's own code raised it; origin timer-spawn-probe)
[ERROR] MCP server "timer-spawn-probe" timer-spawn-probe registered the tool ping but no tool.call hook answered this call: ...
[DEBUG] MCP server "timer-spawn-probe": Tool 'ping' failed after 0s: timer-spawn-probe registered the tool ping but no tool.call hook answered this call: ..

Steps to Reproduce

A minimal mod with agents/pinger.md (tools: ToolSearch, mcp__spawnprobe__ping), a tool.call hook that returns { result: 'pong' }, and a /probe command.
In /probe, spawning spawnprobe:pinger directly works.
In /probe, wrapping the same spawn in $.clock.after(500, ...) fails as above.
It fails the same way with general-purpose instead of a plugin agent type.

https://gist.github.com/cbundy/8b1a0fa00dc3b0806e24040d70342be1

agent spawned inside command.run: reaches the hook
[DEBUG] hooks module timer-spawn-probe@inline: tool.call nested in timer-spawn-probe#2

agent spawned from $.clock.after: hook skipped

[DEBUG] hooks module timer-spawn-probe@inline tool.call skipped: re-entry (the plugin's own code raised it; origin timer-spawn-probe)
[ERROR] MCP server "timer-spawn-probe" timer-spawn-probe registered the tool ping but no tool.call hook answered this call: ...
[DEBUG] MCP server "timer-spawn-probe": Tool 'ping' failed after 0s: timer-spawn-probe registered the tool ping but no tool.call hook answered this call: ... 

Claude Model

Opus

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.1.299

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Non-interactive/CI environment

Additional Information

Impact: any mod that drives agents from a timer can’t use its own tools as a structured channel back from those agents. Our orchestration mod’s passes run on $.clock.every, so every agent tool call failed: more than 80 in one session. We’ve had to fall back to agents running a validation script through Bash.

Related, possibly worth a docs note: a tool.call hook that runs past its 10 s HookBudget returns the same “no tool.call hook answered this call” message, even though the hook did run. With identical messages the two causes look the same, and it cost us a while to tell them apart. A message that says which happened would help.

View original on GitHub ↗