fix(agents): make librarian failures structured and user-safe
- run_librarian / run_librarian_stream raise AgentError instead of
returning/yielding error text as normal output; detail stays in logs
- delegate_to_* wrappers now put a curated butler-toned sentence in
DelegationResult.output on failure and never expose str(e), so
streaming's error branch is reachable and honest
- _execute_single_delegation propagates success; direct delegation only
records delegate_to_* as called when the expert actually succeeded
- librarian tools return user-safe messages instead of
'Error searching: {e}' strings that leaked internal URLs into
synthesis; coordination stream errors are curated as well
- ruff cleanups (TYPE_CHECKING forward refs, B904, unused locals) in
the touched files to keep them lint-clean
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+19
-12
@@ -8,12 +8,12 @@ returns a structured result for synthesis.
|
||||
This implements the agent-as-tool pattern recommended by PydanticAI:
|
||||
agents call other agents via tool wrappers, keeping each agent focused.
|
||||
"""
|
||||
from collections.abc import AsyncGenerator
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import AsyncGenerator, Callable, Optional, Any
|
||||
|
||||
from src.core.logging_config import get_logger
|
||||
from src.core.tracing import trace_span, SpanType
|
||||
from src.core.tracing import SpanType, trace_span
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -167,7 +167,7 @@ class DelegationTask:
|
||||
action: str = ""
|
||||
priority: int = 0
|
||||
depends_on: list[str] = field(default_factory=list)
|
||||
result: Optional[str] = None
|
||||
result: str | None = None
|
||||
task_id: str = ""
|
||||
|
||||
def __post_init__(self):
|
||||
@@ -186,14 +186,16 @@ class DelegationResult:
|
||||
expert_name: Which expert handled the task
|
||||
task: Original task description
|
||||
success: Whether the delegation succeeded
|
||||
output: Expert's response/findings
|
||||
error: Error message if failed
|
||||
output: Expert's response/findings. On failure this holds a
|
||||
curated, user-safe butler sentence (never exception detail)
|
||||
error: Short user-safe error label if failed. Exception detail
|
||||
stays in the logs only
|
||||
"""
|
||||
expert_name: str
|
||||
task: str
|
||||
success: bool
|
||||
output: str
|
||||
error: Optional[str] = None
|
||||
error: str | None = None
|
||||
|
||||
|
||||
async def delegate_to_librarian(
|
||||
@@ -285,12 +287,15 @@ async def delegate_to_librarian(
|
||||
span.metadata["success"] = False
|
||||
span.details["error"] = str(e)
|
||||
|
||||
# Exception detail stays in the logs; the user-facing output
|
||||
# is a curated butler sentence so internals never leak into
|
||||
# synthesis.
|
||||
return DelegationResult(
|
||||
expert_name="librarian",
|
||||
task=task,
|
||||
success=False,
|
||||
output="",
|
||||
error=str(e),
|
||||
output=get_think_message("librarian", task, "error"),
|
||||
error="The Librarian was unable to complete the task.",
|
||||
)
|
||||
|
||||
|
||||
@@ -383,12 +388,13 @@ async def delegate_to_biographer(
|
||||
span.metadata["success"] = False
|
||||
span.details["error"] = str(e)
|
||||
|
||||
# Exception detail stays in the logs only.
|
||||
return DelegationResult(
|
||||
expert_name="biographer",
|
||||
task=task,
|
||||
success=False,
|
||||
output="",
|
||||
error=str(e),
|
||||
output=get_think_message("biographer", task, "error"),
|
||||
error="The Biographer was unable to complete the task.",
|
||||
)
|
||||
|
||||
|
||||
@@ -480,12 +486,13 @@ async def delegate_to_housekeeper(
|
||||
span.metadata["success"] = False
|
||||
span.details["error"] = str(e)
|
||||
|
||||
# Exception detail stays in the logs only.
|
||||
return DelegationResult(
|
||||
expert_name="housekeeper",
|
||||
task=task,
|
||||
success=False,
|
||||
output="",
|
||||
error=str(e),
|
||||
output=get_think_message("housekeeper", task, "error"),
|
||||
error="The Housekeeper was unable to complete the task.",
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user