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:
2026-07-14 10:12:30 +02:00
co-authored by Claude Fable 5
parent 59f5b54ac9
commit f853db8ccc
10 changed files with 277 additions and 140 deletions
+14 -14
View File
@@ -111,7 +111,7 @@ async def hybrid_search(
except Exception as e:
logger.error("librarian_hybrid_search_error", error=str(e), query=query)
return f"Error searching: {str(e)}"
return "I was unable to search the knowledge archives; the search service did not respond properly."
# ============================================================================
@@ -159,7 +159,7 @@ async def search_wiki(
except Exception as e:
logger.error("librarian_wiki_search_error", error=str(e))
return f"Error searching wiki: {str(e)}"
return "I was unable to search the wiki at this time."
async def get_wiki_page(
@@ -202,7 +202,7 @@ async def get_wiki_page(
except Exception as e:
logger.error("librarian_get_page_error", error=str(e), page_id=page_id)
return f"Error getting page {page_id}: {str(e)}"
return f"I was unable to retrieve wiki page {page_id}."
async def list_dossiers() -> str:
@@ -236,7 +236,7 @@ async def list_dossiers() -> str:
except Exception as e:
logger.error("librarian_list_dossiers_error", error=str(e))
return f"Error listing dossiers: {str(e)}"
return "I was unable to retrieve the list of dossiers."
async def get_dossier_pages(
@@ -277,7 +277,7 @@ async def get_dossier_pages(
except Exception as e:
logger.error("librarian_get_dossier_error", error=str(e))
return f"Error getting dossier: {str(e)}"
return f"I was unable to retrieve the dossier '{dossier_name}'."
# ============================================================================
@@ -326,7 +326,7 @@ async def semantic_search(
except Exception as e:
logger.error("librarian_semantic_search_error", error=str(e))
return f"Error in semantic search: {str(e)}"
return "I was unable to complete the semantic search."
# ============================================================================
@@ -379,7 +379,7 @@ async def explore_knowledge_graph(
except Exception as e:
logger.error("librarian_explore_graph_error", error=str(e))
return f"Error exploring knowledge graph: {str(e)}"
return "I was unable to explore the knowledge graph."
async def find_related_entities(
@@ -450,7 +450,7 @@ async def find_related_entities(
except Exception as e:
logger.error("librarian_find_related_error", error=str(e))
return f"Error finding related entities: {str(e)}"
return f"I was unable to look up entities related to '{entity_name}'."
# ============================================================================
@@ -533,7 +533,7 @@ async def search_web(
except Exception as e:
logger.error("librarian_web_search_error", error=str(e), query=query)
return f"Error searching web: {str(e)}"
return "I was unable to search the web at this time."
async def read_url(
@@ -609,7 +609,7 @@ async def read_url(
except Exception as e:
logger.error("librarian_read_url_error", error=str(e), url=url)
return f"Error reading URL: {str(e)}"
return f"I was unable to read the page at {url}."
async def read_urls_batch(
@@ -683,7 +683,7 @@ async def read_urls_batch(
except Exception as e:
logger.error("librarian_read_urls_batch_error", error=str(e))
return f"Error reading URLs: {str(e)}"
return "I was unable to read the requested pages."
# ============================================================================
@@ -766,7 +766,7 @@ async def update_wiki_page(
except Exception as e:
logger.error("librarian_update_page_error", error=str(e), page_id=page_id)
return f"Error updating page {page_id}: {str(e)}"
return f"I was unable to update wiki page {page_id}."
async def create_wiki_page(
@@ -841,7 +841,7 @@ async def create_wiki_page(
except Exception as e:
logger.error("librarian_create_page_error", error=str(e), title=title)
return f"Error creating page: {str(e)}"
return f"I was unable to create the page '{title}'."
async def smart_create_wiki_page(
@@ -930,7 +930,7 @@ async def smart_create_wiki_page(
except Exception as e:
logger.error("librarian_smart_create_error", error=str(e), topic=topic)
return f"Error creating page about '{topic}': {str(e)}"
return f"I was unable to create a page about '{topic}'."
# ============================================================================