fix(agent): preserve core hook failure semantics

This commit is contained in:
Xubin Ren
2026-03-31 02:19:29 +08:00
committed by Xubin Ren
parent 758c4e74c9
commit 842b8b255d
3 changed files with 9 additions and 15 deletions
+2 -4
View File
@@ -2,10 +2,10 @@
from nanobot.agent.context import ContextBuilder from nanobot.agent.context import ContextBuilder
from nanobot.agent.hook import AgentHook, AgentHookContext, CompositeHook from nanobot.agent.hook import AgentHook, AgentHookContext, CompositeHook
from nanobot.agent.loop import AgentLoop, LoopHook from nanobot.agent.loop import AgentLoop
from nanobot.agent.memory import MemoryStore from nanobot.agent.memory import MemoryStore
from nanobot.agent.skills import SkillsLoader from nanobot.agent.skills import SkillsLoader
from nanobot.agent.subagent import SubagentHook, SubagentManager from nanobot.agent.subagent import SubagentManager
__all__ = [ __all__ = [
"AgentHook", "AgentHook",
@@ -13,9 +13,7 @@ __all__ = [
"AgentLoop", "AgentLoop",
"CompositeHook", "CompositeHook",
"ContextBuilder", "ContextBuilder",
"LoopHook",
"MemoryStore", "MemoryStore",
"SkillsLoader", "SkillsLoader",
"SubagentHook",
"SubagentManager", "SubagentManager",
] ]
+4 -5
View File
@@ -37,12 +37,11 @@ if TYPE_CHECKING:
from nanobot.cron.service import CronService from nanobot.cron.service import CronService
class LoopHook(AgentHook): class _LoopHook(AgentHook):
"""Core lifecycle hook for the main agent loop. """Core lifecycle hook for the main agent loop.
Handles streaming delta relay, progress reporting, tool-call logging, Handles streaming delta relay, progress reporting, tool-call logging,
and think-tag stripping. Public so downstream users can subclass or and think-tag stripping for the built-in agent path.
compose it via :class:`CompositeHook`.
""" """
def __init__( def __init__(
@@ -105,7 +104,7 @@ class LoopHook(AgentHook):
class _LoopHookChain(AgentHook): class _LoopHookChain(AgentHook):
"""Run the core loop hook first, then best-effort extra hooks. """Run the core loop hook first, then best-effort extra hooks.
This preserves the historical failure behavior of ``LoopHook`` while still This preserves the historical failure behavior of ``_LoopHook`` while still
letting user-supplied hooks opt into ``CompositeHook`` isolation. letting user-supplied hooks opt into ``CompositeHook`` isolation.
""" """
@@ -325,7 +324,7 @@ class AgentLoop:
``resuming=True`` means tool calls follow (spinner should restart); ``resuming=True`` means tool calls follow (spinner should restart);
``resuming=False`` means this is the final response. ``resuming=False`` means this is the final response.
""" """
loop_hook = LoopHook( loop_hook = _LoopHook(
self, self,
on_progress=on_progress, on_progress=on_progress,
on_stream=on_stream, on_stream=on_stream,
+3 -6
View File
@@ -21,11 +21,8 @@ from nanobot.config.schema import ExecToolConfig
from nanobot.providers.base import LLMProvider from nanobot.providers.base import LLMProvider
class SubagentHook(AgentHook): class _SubagentHook(AgentHook):
"""Logging-only hook for subagent execution. """Logging-only hook for subagent execution."""
Public so downstream users can subclass or compose via :class:`CompositeHook`.
"""
def __init__(self, task_id: str) -> None: def __init__(self, task_id: str) -> None:
self._task_id = task_id self._task_id = task_id
@@ -138,7 +135,7 @@ class SubagentManager:
tools=tools, tools=tools,
model=self.model, model=self.model,
max_iterations=15, max_iterations=15,
hook=SubagentHook(task_id), hook=_SubagentHook(task_id),
max_iterations_message="Task completed but no final response was generated.", max_iterations_message="Task completed but no final response was generated.",
error_message=None, error_message=None,
fail_on_tool_error=True, fail_on_tool_error=True,