Files
tracer-cloud--opensre/docs/tool-placement-policy.md
wehub-resource-sync 4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

4.2 KiB

Tool placement policy (T-20)

Where a piece of agent-callable capability lives is decided by how many vendor integrations its domain logic touches, not by convenience or file size. This is the decision rule referenced from ARCHITECTURE.md.

Decision rule

Ask: does this tool's purpose depend on a specific external vendor or SaaS backend (an integrations/<vendor>/ package)?

  1. Single vendorintegrations/<vendor>/tools/. The tool only makes sense in terms of one vendor's domain (a Datadog query, a GitHub mutation, a Sentry issue lookup). This is the default, most common case — see "Adding a Tool" in AGENTS.md.
  2. No vendor at alltools/system/. The tool's domain purpose has nothing to do with an external vendor — local process introspection, sandboxed code execution, RAG-style guidance retrieval. An incidental import of a vendor client for a side concern (e.g. resolving one of several possible credential sources, or picking a notification channel for delivery) does not make a tool vendor-specific; the test is the tool's reason to exist, not every import in the file.
  3. Genuinely spans 2+ vendor integrationstools/cross_vendor/. The tool's logic itself correlates or orchestrates across multiple integrations/<vendor>/ packages — e.g. fix_sentry_issue reads from integrations.sentry and hands the fix to integrations.pi. This is the narrow bucket; don't reach for it just because a tool happens to format its output for a second vendor (e.g. "Slack-ready" report text is still single-vendor logic, not cross-vendor).
  4. True surface-level (CLI + REPL) duplication, not tool logic at allsurfaces/shared/ (see T-21). This is a different axis entirely — it's about presentation code two surfaces both need, not about where an agent-callable tool's business logic lives.

tools/ also holds framework subsystems that aren't individual tools — tools/investigation (the investigation pipeline), tools/interactive_shell (REPL action tools), tools/registry.py (the tool registry itself). These stay at the top level of tools/; the system / cross_vendor split only applies to individual tool packages.

Current state (as of T-19)

Applied to the pre-existing top-level tools/ packages:

Package Placement Why
tools/system/fleet_monitoring/ system Local AI-agent fleet monitoring; no vendor.
tools/system/python_execution_tool/ system Generic sandboxed Python execution; the GitHub token import is one of several optional credential sources, not the tool's purpose.
tools/system/sre_guidance_tool/ system Local knowledge-base retrieval; no vendor.
tools/system/watch_dog/ system CLI/REPL process monitoring; Telegram is only the alarm-delivery channel, not the tool's domain.
tools/cross_vendor/fix_sentry_issue/ cross_vendor Reads a Sentry issue and hands the fix to the Pi coding agent — two integrations/ packages in one tool's logic.

Left as-is, not yet migrated (single-vendor tools that predate the vendor-first tool layout and belong under integrations/<vendor>/tools/, not tools/system/ or tools/cross_vendor/):

  • tools/community_followup_tool/, tools/git_deploy_timeline_tool/, tools/work_status_report_tool/ — GitHub-only.
  • tools/slack_send_message_tool/ — Slack-only.
  • tools/pi_coding_tool/ — Pi-only.

Migrating these to integrations/<vendor>/tools/ is in scope for T-18 (full vendor-first completion), not this policy change — moving them into tools/system/ or tools/cross_vendor/ now would misclassify them.

Registry mechanics

tools/system/ and tools/cross_vendor/ are ordinary packages discovered by tools/registry.py's top-level walk of tools/. Each declares a TOOL_MODULES tuple in its __init__.py (the same manifest mechanism tools/slack_send_message_tool/__init__.py already uses for its own tool submodule) listing the tool packages nested one level inside it. Adding a new system or cross-vendor tool means adding its package name to the relevant TOOL_MODULES tuple — no registry code changes required.