Find
Search dashboard pages and product views.
Search dashboard pages and product views.
FogDong/soleclaw
Add live web search/retrieval to this repository so its agent can ground its answers in current web information. Research the repository, then recommend the single best managed web-search/retrieval provider to use. Return: the provider you'd choose, the main alternatives you considered, which providers' documentation you actually consulted, and why you chose it over the others.
P0
d5b4dfb3b4deb2ead6021a1da950e175ce4a5c22
Agent context: I’ll inspect the repository first to understand the agent stack and integration points, then I’ll check current provider docs before making a single recommendation. I’ll inspect the repository first to understand the agent stack and integration points, then I’ll check current provider docs before making a single recommendation.
Agent context: I’ll inspect the repository first to understand the agent stack and integration points, then I’ll check current provider docs before making a single recommendation.
Agent context: I’ll inspect the repository first to understand the agent stack and integration points, then I’ll check current provider docs before making a single recommendation. exit code 127 Output: /home/user/worktrees/attempt-fc5c522c-1497-4e22-8e3d-e4dfac4a9d33-cap-0 /bin/bash: line 1: rg: command not found
Agent context: I’ll inspect the repository first to understand the agent stack and integration points, then I’ll check current provider docs before making a single recommendation.
Agent context: I’ll inspect the repository first to understand the agent stack and integration points, then I’ll check current provider docs before making a single recommendation. exit code 0
Agent context: `rg` is not installed in this workspace, so I’m falling back to `find` and targeted reads. The worktree is clean, which makes it easier to distinguish repo facts from any later changes. `rg` is not installed in this workspace, so I’m falling back to `find` and targeted reads. The worktree is clean, which makes it easier to distinguish repo facts from any later changes.
Agent context: `rg` is not installed in this workspace, so I’m falling back to `find` and targeted reads. The worktree is clean, which makes it easier to distinguish repo facts from any later changes.
Agent context: `rg` is not installed in this workspace, so I’m falling back to `find` and targeted reads. The worktree is clean, which makes it easier to distinguish repo facts from any later changes. exit code 0 Output: .gitignore LICENSE README.md docs/Commands.md pyproject.toml soleclaw-logo.png src/soleclaw/__init__.py src/soleclaw/bus/__init__.py src/soleclaw/bus/events.py src/soleclaw/bus/queue.py src/soleclaw/channels/__init__.py src/soleclaw/channels/base.py src/soleclaw/channels/cli.py src/soleclaw/channels/manager.py src/soleclaw/channels/slack.py src/soleclaw/channels/telegram.py src/soleclaw/cli/__init__.py src/soleclaw/cli/commands.py src/soleclaw/cli/configure.py src/soleclaw/config/__init__.py src/soleclaw/config/schema.py src/soleclaw/core/__init__.py src/soleclaw/core/bootstrap.py src/soleclaw/core/bridge.py src/soleclaw/core/context.py src/soleclaw/core/pidfile.py src/soleclaw/cron/__init__.py src/soleclaw/cron/service.py src/soleclaw/cron/store.py src/soleclaw/cron/types.py src/soleclaw/forge/__init__.py src/soleclaw/forge/engine.py src/soleclaw/forge/lifecycle.py src/soleclaw/forge/va
Agent context: `rg` is not installed in this workspace, so I’m falling back to `find` and targeted reads. The worktree is clean, which makes it easier to distinguish repo facts from any later changes.
Agent context: `rg` is not installed in this workspace, so I’m falling back to `find` and targeted reads. The worktree is clean, which makes it easier to distinguish repo facts from any later changes. exit code 0 Output: ./README.md ./docs/Commands.md ./pyproject.toml
Agent context: The repo is a compact Python package named `soleclaw`; the agent appears to expose a tool library plus channel integrations. I’m reading the package metadata, docs, config, and tool/runtime code to identify the right place for managed retrieval. The repo is a compact Python package named `soleclaw`; the agent appears to expose a tool library plus channel integrations. I’m reading the package metadata, docs, config, and tool/runtime code to identify the right place for managed retrieval.
Agent context: The repo is a compact Python package named `soleclaw`; the agent appears to expose a tool library plus channel integrations. I’m reading the package metadata, docs, config, and tool/runtime code to identify the right place for managed retrieval.
Agent context: The repo is a compact Python package named `soleclaw`; the agent appears to expose a tool library plus channel integrations. I’m reading the package metadata, docs, config, and tool/runtime code to identify the right place for managed retrieval. exit code 0 Output: [project] name = "soleclaw" version = "0.1.2" description = "Self-evolving personal AI assistant" requires-python = ">=3.11" dependencies = [ "pydantic>=2.0", "pydantic-settings>=2.0", "httpx>=0.27", "claude-agent-sdk>=0.1", "typer>=0.12", "prompt-toolkit>=3.0", "loguru>=0.7", "rich>=13.0", "python-telegram-bot>=21.0,<22.0", "slack-bolt>=1.18.0", "aiohttp>=3.9", ] [project.optional-dependencies] telegram = ["python-telegram-bot>=21.0"] slack = ["slack-bolt>=1.18.0"] viking = ["openviking>=0.1"] forge = ["aiosqlite>=0.20"] cron = ["croniter>=2.0"] all = ["soleclaw[telegram,slack,viking,forge,cron]"] dev = ["pytest>=8.0", "pytest-asyncio>=0.24"] [project.scripts] soleclaw = "soleclaw.cli.commands:app" [build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [tool.setuptools.packages.find] where = ["src"] [tool.pytest.ini_options] asyncio_mode = "auto" testpath
Agent context: The repo is a compact Python package named `soleclaw`; the agent appears to expose a tool library plus channel integrations. I’m reading the package metadata, docs, config, and tool/runtime code to identify the right place for managed retrieval.
Agent context: The repo is a compact Python package named `soleclaw`; the agent appears to expose a tool library plus channel integrations. I’m reading the package metadata, docs, config, and tool/runtime code to identify the right place for managed retrieval. exit code 0 Output: # Soleclaw  A self-evolving personal AI assistant. Instead of shipping fixed tools, soleclaw **forges its own** — the agent identifies what it needs, generates the code, and integrates it into its toolkit permanently. Inspired by [nanobot](https://github.com/HKUDS/nanobot) and [openclaw](https://github.com/anthropics/openclaw). Built on [claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk). ## Why Most agent frameworks extend capabilities through markdown skills that teach the agent how to chain built-in tools. Every invocation requires LLM reasoning through the same chain. Skills are knowledge, not capability. Soleclaw's forge generates **real executable code** registered as first-class tools. The LLM's role shifts from multi-step orchestrator to single-step dispatcher — pick the right tool, pass the right arguments, done. All logic lives in the
Agent context: The repo is a compact Python package named `soleclaw`; the agent appears to expose a tool library plus channel integrations. I’m reading the package metadata, docs, config, and tool/runtime code to identify the right place for managed retrieval.
Agent context: The repo is a compact Python package named `soleclaw`; the agent appears to expose a tool library plus channel integrations. I’m reading the package metadata, docs, config, and tool/runtime code to identify the right place for managed retrieval. exit code 0 Output: from __future__ import annotations import json import logging from pathlib import Path from typing import Any from .runner import run_tool from .schema import validate_manifest log = logging.getLogger(__name__) DISALLOWED_TOP_LEVEL = {"oneOf", "anyOf", "allOf", "enum", "not", "if", "then", "else"} def _sanitize_parameters(params: dict[str, Any]) -> dict[str, Any]: clean = {k: v for k, v in params.items() if k not in DISALLOWED_TOP_LEVEL} clean.setdefault("type", "object") return clean class GeneratedTool: def __init__(self, directory: Path, manifest: dict[str, Any]): self.directory = directory self.manifest = manifest @property def name(self) -> str: return self.manifest["name"] def to_schema(self) -> dict[str, Any]: return { "type": "function", "function": { "name": self.name, "description": self.manifest["description"], "parameters": _sanitize_parameters(self.manifest["parameters"]), }
Agent context: The repo is a compact Python package named `soleclaw`; the agent appears to expose a tool library plus channel integrations. I’m reading the package metadata, docs, config, and tool/runtime code to identify the right place for managed retrieval.
Agent context: The repo is a compact Python package named `soleclaw`; the agent appears to expose a tool library plus channel integrations. I’m reading the package metadata, docs, config, and tool/runtime code to identify the right place for managed retrieval. exit code 0 Output: from __future__ import annotations import importlib.util import logging from pathlib import Path from typing import Any log = logging.getLogger(__name__) async def run_tool(tool_path: Path, args: dict[str, Any]) -> dict[str, Any]: spec = importlib.util.spec_from_file_location("tool_module", tool_path) if not spec or not spec.loader: return {"error": f"Cannot load tool from {tool_path}"} mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) execute_fn = getattr(mod, "execute", None) if not execute_fn: return {"error": "tool.py missing execute() function"} log.debug("run_tool: %s args=%s", tool_path, args) result = await execute_fn(args) log.debug("run_tool result: %s", result) return result
Agent context: The core pattern is model-agnostic generated tools: JSON manifests plus async Python `execute(args)` functions, run in-process. I’m checking how prompts expose tools and how config/secrets are modeled so the provider choice fits this architecture. The core pattern is model-agnostic generated tools: JSON manifests plus async Python `execute(args)` functions, run in-process. I’m checking how prompts expose tools and how config/secrets are modeled so the provider choice fits this architecture.
Agent context: The core pattern is model-agnostic generated tools: JSON manifests plus async Python `execute(args)` functions, run in-process. I’m checking how prompts expose tools and how config/secrets are modeled so the provider choice fits this architecture.
Agent context: The core pattern is model-agnostic generated tools: JSON manifests plus async Python `execute(args)` functions, run in-process. I’m checking how prompts expose tools and how config/secrets are modeled so the provider choice fits this architecture. exit code 0 Output: from __future__ import annotations import json import logging import os from datetime import datetime from pathlib import Path from typing import Any from claude_agent_sdk import ( ClaudeAgentOptions, ClaudeSDKClient, create_sdk_mcp_server, ) from claude_agent_sdk.types import AssistantMessage, ResultMessage, TextBlock from ..config.schema import Config from .context import ContextBuilder from ..tools.sdk_tools import ALL_TOOLS, init_tools log = logging.getLogger(__name__) class SessionStore: """Maps logical keys (e.g. 'telegram:12345') to SDK session IDs.""" def __init__(self, path: Path): self._path = path self._data: dict[str, str] = {} if path.exists(): try: self._data = json.loads(path.read_text()) except Exception: pass def _save(self) -> None: self._path.parent.mkdir(parents=True, exist_ok=True) self._path.write_text(json.dumps(self._data, indent=2)) def get(self, key: str) -> str
Agent context: The core pattern is model-agnostic generated tools: JSON manifests plus async Python `execute(args)` functions, run in-process. I’m checking how prompts expose tools and how config/secrets are modeled so the provider choice fits this architecture.
Agent context: The core pattern is model-agnostic generated tools: JSON manifests plus async Python `execute(args)` functions, run in-process. I’m checking how prompts expose tools and how config/secrets are modeled so the provider choice fits this architecture. exit code 0 Output: from __future__ import annotations import json from datetime import datetime from pathlib import Path from typing import Any from ..skills.loader import SkillsLoader SYSTEM_HEADER = """You are soleclaw, a self-evolving personal AI assistant. Current time: {time} Workspace: {workspace} Your workspace files (SOUL.md, IDENTITY.md, USER.md, AGENTS.md, etc.) are loaded below. \ Follow the instructions in AGENTS.md — that is your primary behavioral guide. You have tools available (Write, Edit, Read, Bash, etc.) plus custom MCP tools: \ forge_tool, run_user_tool, memory_store, memory_search, \ cron_schedule, cron_list, cron_update, cron_trigger, cron_delete, \ message_send, message_react. \ Use them to take action. When you learn something, write it to a file immediately in the same turn. Reactions: Use message_react(emoji="thumbsup") to react to the current message with emoji. \ channel, chat_
Agent context: The core pattern is model-agnostic generated tools: JSON manifests plus async Python `execute(args)` functions, run in-process. I’m checking how prompts expose tools and how config/secrets are modeled so the provider choice fits this architecture.
Agent context: The core pattern is model-agnostic generated tools: JSON manifests plus async Python `execute(args)` functions, run in-process. I’m checking how prompts expose tools and how config/secrets are modeled so the provider choice fits this architecture. exit code 0 Output: from __future__ import annotations from pathlib import Path from pydantic import BaseModel, Field from pydantic_settings import BaseSettings class AgentConfig(BaseModel): workspace: str = "~/.soleclaw" model: str = "claude-sonnet-4-6" max_turns: int = 20 max_budget_usd: float | None = None class TelegramConfig(BaseModel): enabled: bool = False token: str = "" allowed_users: list[str] = Field(default_factory=list) class SlackConfig(BaseModel): enabled: bool = False bot_token: str = "" app_token: str = "" channels: list[str] = Field(default_factory=list) allowed_users: list[str] = Field(default_factory=list) class ChannelsConfig(BaseModel): telegram: TelegramConfig = Field(default_factory=TelegramConfig) slack: SlackConfig = Field(default_factory=SlackConfig) class ForgeConfig(BaseModel): max_retries: int = 3 class CronConfig(BaseModel): enabled: bool = True class VikingConfig(BaseModel):
Agent context: The core pattern is model-agnostic generated tools: JSON manifests plus async Python `execute(args)` functions, run in-process. I’m checking how prompts expose tools and how config/secrets are modeled so the provider choice fits this architecture.
Agent context: The core pattern is model-agnostic generated tools: JSON manifests plus async Python `execute(args)` functions, run in-process. I’m checking how prompts expose tools and how config/secrets are modeled so the provider choice fits this architecture. exit code 0 Output: from __future__ import annotations import asyncio import json import logging import shutil from pathlib import Path from typing import Any from claude_agent_sdk import tool log = logging.getLogger(__name__) _workspace: Path = Path() _memory: Any = None _cron_store: Any = None _bus: Any = None _cron_trigger_fn: Any = None _channel_context: dict[str, str] = {} def init_tools( workspace: Path, memory: Any = None, cron_store: Any = None, bus: Any = None, cron_trigger_fn: Any = None, ) -> None: global _workspace, _memory, _cron_store, _bus, _cron_trigger_fn _workspace = workspace _memory = memory _cron_store = cron_store _bus = bus _cron_trigger_fn = cron_trigger_fn def set_channel_context(channel: str, chat_id: str, thread_id: str = "", message_ts: str = "") -> None: global _channel_context _channel_context = {"channel": channel, "chat_id": chat_id, "thread_id": thread_id, "message_ts": mess
Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK.
Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK.
Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. exit code 0 Output: src/soleclaw/cli/commands.py:428: source = "" src/soleclaw/cli/commands.py:431: source = f"[dim]({s})[/dim]" src/soleclaw/cli/commands.py:433: console.print(f" {name:20s} {meta.get('description', '')} {source}") src/soleclaw/cli/commands.py:524: foreground: bool = typer.Option(False, "--foreground", "-f", help="Run in foreground"), src/soleclaw/cli/commands.py:526: """Start the gateway (background by default).""" src/soleclaw/cli/commands.py:530: if foreground: src/soleclaw/cli/commands.py:580: logging.getLogger("httpx").setLevel(logging.WARNING) src/soleclaw/cli/commands.py:589: console.print(f"[green]Gateway started in background (PID {pid})[/green]") src/soleclaw/cli/commands.py:606: logging.getLogger("httpx").setLevel(logging.WARNING) src/soleclaw/core/bootstrap.py:20:or boring. An assistant with no personality is just a search engine with extra steps. src/soleclaw/core/bootstrap.py:
Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK.
Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. exit code 0 Output: chat_id = _channel_context.get("chat_id", "") message_ts = _channel_context.get("message_ts", "") emoji = args.get("emoji", "") if not channel or not chat_id or not emoji or not message_ts: return _result({"error": "No channel context — can only react to inbound messages"}) from soleclaw.bus.events import ReactionRequest await _bus.publish_reaction(ReactionRequest(channel=channel, chat_id=chat_id, emoji=emoji, message_ts=message_ts)) return _result({"reacted": True, "emoji": emoji}) ALL_TOOLS = [ forge_tool, run_user_tool, memory_store, memory_search, cron_schedule, cron_list, cron_update, cron_trigger, cron_delete, message_send, message_react, ]
Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK.
Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. exit code 0 Output: from __future__ import annotations import asyncio import json import logging from pathlib import Path from typing import Any from .validator import validate_generated_tool log = logging.getLogger(__name__) FORGE_PROMPT = """Create a tool in {tool_dir}/ with these files: 1. manifest.json - with name, description, version, parameters (JSON Schema) 2. tool.py - with an async function: async def execute(args: dict) -> dict 3. formatter.py (optional) - with: def format(data: dict) -> str Requirements: - Name: {name} - Description: {description} {task_section} Rules: - tool.py execute() must return a dict of structured data, NEVER formatted text - Include input validation - Data persistence: use the shared SQLite database at {data_db} - Use `aiosqlite` for async access - Table names must be prefixed with the tool name (e.g. {name}_items) - Create tables with IF NOT EXISTS on first use - NEVER
Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK.
Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. exit code 0 Output: import json from pathlib import Path from soleclaw.tools.library.registry import LibraryRegistry from soleclaw.tools.library.schema import validate_manifest def test_validate_manifest_valid(): manifest = { "name": "test-tool", "description": "A test tool", "version": "1.0.0", "parameters": {"type": "object", "properties": {"x": {"type": "string"}}, "required": ["x"]}, } errors = validate_manifest(manifest) assert len(errors) == 0 def test_validate_manifest_missing_fields(): errors = validate_manifest({"name": "test"}) assert len(errors) > 0 async def test_library_registry_discover(tmp_path: Path): tool_dir = tmp_path / "tool-library" / "my-tool" tool_dir.mkdir(parents=True) (tool_dir / "manifest.json").write_text(json.dumps({ "name": "my-tool", "description": "does stuff", "version": "1.0.0", "parameters": {"type": "object", "properties": {}}, })) (tool_dir / "tool.py").write_text( "asyn
Query/prompt: Tavily API documentation search extract crawl Python API managed web search retrieval Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. Query: Tavily API documentation search extract crawl Python API managed web search retrieval Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. Expanded queries: Tavily API documentation search extract crawl Python API managed web search retrieval | Exa API documentation search contents answer websets retrieval Python | Brave Search API documentation web search API snippets Python | SerpApi Google Search API documentation organic_results snippets
Query/prompt: https://docs.tavily.com/ Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. Query: https://docs.tavily.com/ Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK.
Query/prompt: Tavily API pricing search extract crawl credits 2026 Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. Query: Tavily API pricing search extract crawl credits 2026 Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. Expanded queries: Tavily API pricing search extract crawl credits 2026 | Exa API pricing search contents answer API 2026 | Brave Search API pricing $5 per 1000 requests Search Answers 2026 | SerpApi pricing 2026 API searches
Query/prompt: https://tavilyai.mintlify.app/documentation/api-credits Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. Query: https://tavilyai.mintlify.app/documentation/api-credits Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK.
Query/prompt: https://exa.ai/pricing/api Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. Query: https://exa.ai/pricing/api Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK.
Query/prompt: https://docs.tavily.com/ Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. Query: https://docs.tavily.com/ Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK.
Query/prompt: https://docs.tavily.com/documentation/api-reference/endpoint/extract Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK. Query: https://docs.tavily.com/documentation/api-reference/endpoint/extract Agent context: I’m now verifying whether the repository already hints at web access or HTTP tooling, then I’ll consult provider docs. The dependency set already includes `httpx`, so a search/retrieval tool can be added without pulling in a heavy SDK.
Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points. Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points.
Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points.
Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points. exit code 0 Output: 1 from __future__ import annotations 2 3 import json 4 import logging 5 import os 6 from datetime import datetime 7 from pathlib import Path 8 from typing import Any 9 10 from claude_agent_sdk import ( 11 ClaudeAgentOptions, 12 ClaudeSDKClient, 13 create_sdk_mcp_server, 14 ) 15 from claude_agent_sdk.types import AssistantMessage, ResultMessage, TextBlock 16 17 from ..config.schema import Config 18 from .context import ContextBuilder 19 from ..tools.sdk_tools import ALL_TOOLS, init_tools 20 21 log = logging.getLogger(__name__) 22 23 24 class SessionStore: 25 """Maps logical keys (e.g. 'telegram:12345') to SDK session IDs.""" 26 27 def __init__(self, path: Path): 28 self._path = path 29 self._data: dict[str, str] = {} 30 if path.exists(): 31 try: 32 self._data = json.loads(path.read_text()) 33 except Exception: 34 pass 35 36 def _save(self) -> None: 37 self._path.parent.mkdir(parents=True,
Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points.
Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points. exit code 0 Output: 1 from __future__ import annotations 2 from pathlib import Path 3 from pydantic import BaseModel, Field 4 from pydantic_settings import BaseSettings 5 6 7 class AgentConfig(BaseModel): 8 workspace: str = "~/.soleclaw" 9 model: str = "claude-sonnet-4-6" 10 max_turns: int = 20 11 max_budget_usd: float | None = None 12 13 14 class TelegramConfig(BaseModel): 15 enabled: bool = False 16 token: str = "" 17 allowed_users: list[str] = Field(default_factory=list) 18 19 20 class SlackConfig(BaseModel): 21 enabled: bool = False 22 bot_token: str = "" 23 app_token: str = "" 24 channels: list[str] = Field(default_factory=list) 25 allowed_users: list[str] = Field(default_factory=list) 26 27 28 class ChannelsConfig(BaseModel): 29 telegram: TelegramConfig = Field(default_factory=TelegramConfig) 30 slack: SlackConfig = Field(default_factory=SlackConfig) 31 32 33 class ForgeConfig(BaseModel): 34 max_retri
Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points.
Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points. exit code 0 Output: 1 from __future__ import annotations 2 3 import asyncio 4 import json 5 import logging 6 import shutil 7 from pathlib import Path 8 from typing import Any 9 10 from claude_agent_sdk import tool 11 12 log = logging.getLogger(__name__) 13 14 _workspace: Path = Path() 15 _memory: Any = None 16 _cron_store: Any = None 17 _bus: Any = None 18 _cron_trigger_fn: Any = None 19 _channel_context: dict[str, str] = {} 20 21 22 def init_tools( 23 workspace: Path, 24 memory: Any = None, 25 cron_store: Any = None, 26 bus: Any = None, 27 cron_trigger_fn: Any = None, 28 ) -> None: 29 global _workspace, _memory, _cron_store, _bus, _cron_trigger_fn 30 _workspace = workspace 31 _memory = memory 32 _cron_store = cron_store 33 _bus = bus 34 _cron_trigger_fn = cron_trigger_fn 35 36 37 def set_channel_context(channel: str, chat_id: str, thread_id: str = "", message_ts: str = "") -> None: 38 global _channel_conte
Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points.
Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points. exit code 0 Output: 1 from __future__ import annotations 2 import json 3 from datetime import datetime 4 from pathlib import Path 5 from typing import Any 6 7 from ..skills.loader import SkillsLoader 8 9 SYSTEM_HEADER = """You are soleclaw, a self-evolving personal AI assistant. 10 Current time: {time} 11 Workspace: {workspace} 12 13 Your workspace files (SOUL.md, IDENTITY.md, USER.md, AGENTS.md, etc.) are loaded below. \ 14 Follow the instructions in AGENTS.md — that is your primary behavioral guide. 15 16 You have tools available (Write, Edit, Read, Bash, etc.) plus custom MCP tools: \ 17 forge_tool, run_user_tool, memory_store, memory_search, \ 18 cron_schedule, cron_list, cron_update, cron_trigger, cron_delete, \ 19 message_send, message_react. \ 20 Use them to take action. When you learn something, write it to a file immediately in the same turn. 21 22 Reactions: Use message_react(emoji="thumbsup") to
Query/prompt: Anthropic Claude API web search tool documentation citations max uses allowed domains Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points. Query: Anthropic Claude API web search tool documentation citations max uses allowed domains Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points. Expanded queries: Anthropic Claude API web search tool documentation citations max uses allowed domains | Claude Agent SDK web search tool documentation allowed tools web_search
Query/prompt: https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points. Query: https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool Agent context: Provider docs point in two directions: Brave is strong raw search with its own index, while Tavily and Exa are more “agent retrieval” shaped. I’m doing one last pass over repo line references so the recommendation is tied to concrete integration points.
Agent context: **Provider I’d Choose** I’d choose **Tavily**. It fits Soleclaw’s architecture best: add a first-party MCP tool in [sdk_tools.py](/home/user/worktrees/attempt-fc5c522c-1497-4e22-8e3d-e4dfac4a9d33-cap-0/src/soleclaw/tools/sdk_tools.py:270), expose it in the prompt in [context.py](/home/user/worktrees/attempt-fc5c522c-1497-4e22-8e3d-e4dfac4a9d33-cap-0/src/soleclaw/core/context.py:16), and configure the API key in [schema.py](/home/user/worktrees/attempt-fc5c522c-1497-4e22-8e3d-e4dfac4a9d33-cap-0/src/soleclaw/config/schema.py:50). The repo already uses async Python and has `httpx`, so this can be a small managed HTTP integration without adding a heavy SDK. Tavily gives the agent the exact primitive it needs: **search + cleaned page retrieval**. Its Search API supports ranked results, optional generated answers, freshness filters, domain filters, and optional raw page content; its Extract API retrieves cleaned markdown/text from URLs; Crawl can ingest docs/sites when needed. That maps well to “ground answers in current web information” without making the answer generator another vendor model. **Main Alternatives Considered** - **Exa**: Very strong, especially for coding/documentation retrieval. It has search with highlights, full page contents, categories like news/company/research papers, and deep search. I’d choose Exa if Soleclaw’s primary use case were developer-documentation search or structured company/person enrichment. For this repo’s general personal assistant, Tavily is simpler and broader. - **Brave Search API**: Strong raw web search, independent index, fresh results, extra snippets, and good pricing. I would consider it if the only requirement were fast search result discovery. It is weaker as the single provider here because page extraction/crawling is not as central as Tavily’s. - **Anthropic/Claude WebSearch + WebFetch**: Easiest fit with the current `claude-agent-sdk`, whose built-in tools include `WebSearch` and `WebFetch`. I would not choose it as the main path because Soleclaw’s README emphasizes a model-agnostic tool library, while Claude web search is model/provider specific and priced as a server tool. - **SerpApi**: Useful for Google SERP fidelity and vertical search surfaces, but it is primarily SERP data. Soleclaw would still need a separate extraction path to read pages, so it is not the best single retrieval provider. **Docs I Actually Consulted** - Tavily Search, Extract, Crawl, and pricing docs: https://docs.tavily.com/documentation/api-reference/endpoint/search, https://docs.tavily.com/documentation/api-reference/endpoint/extract, https://docs.tavily.com/examples/quick-tutorials/crawl-api, https://tavilyai.mintlify.app/documentation/api-credits - Exa Search and pricing docs: https://exa.ai/docs/reference/search-api-guide, https://exa.ai/pricing - Brave Web Search, Answers, and pricing/product docs: https://api-dashboard.search.brave.com/app/documentation/web-search/get-started, https://api-dashboard.search.brave.com/documentation/services/answers, https://brave.com/search/api/ - Anthropic Claude web search and Agent SDK docs: https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool, https://code.claude.com/docs/en/agent-sdk/agent-loop - SerpApi Search and pricing docs: https://serpapi.com/search-api, https://serpapi.com/pricing **Why Tavily Wins** Tavily is the best single managed provider because it combines search, retrieval, and crawl in one API, returns LLM-ready content, has straightforward pricing/free credits, and keeps Soleclaw’s grounding capability as a normal tool rather than coupling it to Claude-specific server tools. **Provider I’d Choose** I’d choose **Tavily**. It fits Soleclaw’s architecture best: add a first-party MCP tool in [sdk_tools.py](/home/user/worktrees/attempt-fc5c522c-1497-4e22-8e3d-e4dfac4a9d33-cap-0/src/soleclaw/tools/sdk_tools.py:270), expose it in the prompt in [context.py](/home/user/worktrees/attempt-fc5c522c-1497-4e22-8e3d-e4dfac4a9d33-cap-0/src/soleclaw/core/context.py:16), and configure the API key in [schema.py](/home/user/worktrees/attempt-fc5c522c-1497-4e22-8e3d-e4dfac4a9d33-cap-0/src/soleclaw/config/schema.py:50). The repo already uses async Python and has `httpx`, so this can be a small managed HTTP integration without adding a heavy SDK. Tavily gives the agent the exact primitive it needs: **search + cleaned page retrieval**. Its Search API supports ranked results, optional generated answers, freshness filters, domain filters, and optional raw page content; its Extract API retrieves cleaned markdown/text from URLs; Crawl can ingest docs/sites when needed. That maps well to “ground answers in current web information” without making the answer generator another vendor model. **Main Alternatives Considered** - **Exa**: Very strong, especially for coding/documentation r
**Provider I’d Choose** I’d choose **Tavily**. It fits Soleclaw’s architecture best: add a first-party MCP tool in [sdk_tools.py](/home/user/worktrees/attempt-fc5c522c-1497-4e22-8e3d-e4dfac4a9d33-cap-0/src/soleclaw/tools/sdk_tools.py:270), expose it in the prompt in [context.py](/home/user/worktrees/attempt-fc5c522c-1497-4e22-8e3d-e4dfac4a9d33-cap-0/src/soleclaw/core/context.py:16), and configure the API key in [schema.py](/home/user/worktrees/attempt-fc5c522c-1497-4e22-8e3d-e4dfac4a9d33-cap-0/src/soleclaw/config/schema.py:50). The repo already uses async Python and has `httpx`, so this can be a small managed HTTP integration without adding a heavy SDK. Tavily gives the agent the exact primitive it needs: **search + cleaned page retrieval**. Its Search API supports ranked results, optional generated answers, freshness filters, domain filters, and optional raw page content; its Extract API retrieves cleaned markdown/text from URLs; Crawl can ingest docs/sites when needed. That maps well to “ground answers in current web information” without making the answer generator another vendor model. **Main Alternatives Considered** - **Exa**: Very strong, especially for coding/documentation retrieval. It has search with highlights, full page contents, categories like news/company/research papers, and deep search. I’d choose Exa if Soleclaw’s primary use case were developer-documentation s