Files
zooqueenandHanzo Dev e7000de487 feat(tools): research action on net/fetch — cited answers over /v1/ask
Search finds pages, web_read reads one, research is the whole loop behind a
single door: the live cloud answer engine (api.hanzo.ai /v1/ask, mode=research)
plans queries, searches, reads the best pages and writes an answer that cites
them. It is an action on the same fetch tool, not a new package — search, read
and research are one concern (the web) and share one client and one auth.

The engine replies as server-sent events, which is the cloud's other reply
shape, so HanzoCloud gains stream() beside get/post: the base URL, the auth
header and the error mapping stay in the one place that already owns them.
Each `data:` frame is yielded as a typed event (status | sources | text |
follow_ups | done | error); the terminal [DONE] sentinel ends the stream and is
never an event. Frames accumulate into {answer, sources, follow_ups}; `deep`
normalizes to `research` (one pass, two names) and any other mode is refused
rather than silently downgraded.

hanzo-tools 0.3.4->0.3.5, -net 0.1.3->0.1.4, and -net's floor moves to
hanzo-tools>=0.3.5 so the action cannot install against a client with no
stream(). Tests replay a canned SSE stream through the real parser.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-04 22:48:19 -07:00

68 lines
1.7 KiB
Python

"""Network tools for Hanzo AI (HIP-0300).
Tools:
- net: Unified network tool (HIP-0300)
- search: Web search (Query → [URL, title, snippet])
- research: Cited answer over the live web (Query → {answer, sources})
- fetch: Retrieve URL content (URL → {text, mime})
- download: Save URL with assets (URL → Path)
- crawl: Recursive site mirror (URL, depth → [Path])
- head: Get headers only
Effect lattice position: NONDETERMINISTIC_EFFECT
All operations involve network I/O.
Install:
pip install hanzo-tools-net
pip install hanzo-tools-net[full] # With beautifulsoup4
Usage:
from hanzo_tools.net import register_tools, TOOLS
# Register with MCP server
register_tools(mcp_server)
# Or access the unified tool
from hanzo_tools.net import NetTool
"""
from hanzo_tools.core import BaseTool, ToolRegistry
from .fetch_tool import FetchTool, fetch_tool
from .vision_tool import VisionTool, vision_tool
# Backward compat
NetTool = FetchTool
net_tool = fetch_tool
# Export list for tool discovery - HIP-0300 unified tools
TOOLS = [FetchTool, VisionTool]
__all__ = [
"FetchTool",
"fetch_tool",
"VisionTool",
"vision_tool",
"NetTool",
"net_tool",
"register_tools",
"TOOLS",
]
def register_tools(mcp_server, **kwargs) -> list[BaseTool]:
"""Register net tools with the MCP server.
Args:
mcp_server: The FastMCP server instance
**kwargs: Additional options (cwd, etc.)
Returns:
List of registered tool instances
"""
cwd = kwargs.get("cwd")
tools: list[BaseTool] = [FetchTool(cwd=cwd), VisionTool(cwd=cwd)]
for tool in tools:
ToolRegistry.register_tool(mcp_server, tool)
return tools