[feat] Tool discovery: POST /tools/discover + reserved find_capabilities tool#4884
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (7)
✅ Files skipped from review due to trivial changes (3)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds Composio-backed tool discovery, server routing for ChangesTool Discovery Workflow
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
🔸 Two things needed here (both your call, not a code review): 1. Design review of the 2. Decisions D2–D6 in
Once you pick (or just say "go with the recommendations"), I'll queue the implementation starting with Phase 1 (the adapter method + a recorded-fixture test). |
| - Capture the Composio response as a replay fixture (`agent-replay-test` skill) so the | ||
| contract is pinned without a live LLM. | ||
|
|
||
| ## Phase 6 — Follow-ups (separate slices) |
There was a problem hiding this comment.
Add as part of the PR a skill to deal with this (not agents.md). And test it using a subagent after this is implemented to see if they can easily setup the tools for an agent
There was a problem hiding this comment.
🤖 The AI agent says: Done. The skill ships in this PR at docs/design/agent-workflows/projects/tool-discovery/skills/discover-and-wire-tools/SKILL.md (the discover, resolve-connections, create, test loop, not an agents.md blob). The subagent setup test you asked for needs a live Composio key, so it runs in the orchestrator's e2e phase (/debug-local plus a setup subagent) after this lands. Phase 5 in plan.md and the note in status.md track it as that follow-up.
| - Optional `manage_connection` helper tool (design note #6) so the agent can initiate a | ||
| connection without composing the raw `POST /tools/connections/` body. | ||
|
|
||
| ## Testing and conventions |
There was a problem hiding this comment.
dont forget spinning off a subagent to qa this explorative with /debug local
There was a problem hiding this comment.
🤖 The AI agent says: Acknowledged. The live /debug-local exploratory QA needs the running stack and a real Composio connection, so it goes to the orchestrator's e2e pass rather than this implementation step. plan.md Phase 5 marks it as that follow-up.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
docs/design/agent-workflows/projects/tool-discovery/research.md (1)
10-21: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd language specifiers to fenced code blocks.
Several code blocks documenting API request/response shapes lack language identifiers. Adding
jsonorjsoncimproves syntax highlighting and readability.♻️ Proposed fixes
+```json
{
"user_id": "",And similarly for the other data-structure blocks at lines 32, 43, 57, 72, 79, 90. </details> Also applies to: 32-39, 43-53, 57-61, 72-75, 79-82, 90-96 <!-- cr-comment:v1:1f9c7a95eba1aa1e570bde7a --> </blockquote></details> <details> <summary>docs/design/agent-workflows/projects/tool-discovery/use-case-walkthrough.md (1)</summary><blockquote> `49-59`: _📐 Maintainability & Code Quality_ | _🔵 Trivial_ | _💤 Low value_ **Add language specifier to the JSON request block.** ```diff+```jsonc
{
"use_cases": [<!-- cr-comment:v1:42f8ea08667123c472586810 --> </blockquote></details> <details> <summary>docs/design/agent-workflows/projects/tool-discovery/plan.md (1)</summary><blockquote> `50-52`: _📐 Maintainability & Code Quality_ | _🔵 Trivial_ | _⚡ Quick win_ **Confirm cache TTL values align with operational requirements.** The plan specifies "existing 5-min TTL" for tool/schema cache and "short TTL for the connection part" without stating the short duration. Document the intended connection-state TTL (e.g., 30s, 60s) or reference the operational SLO for connection freshness to ensure implementers don't default to the same 5-minute window. ```diff - re-resolve connection state fresh each call (it changes when a user connects). Split keys or - short TTL for the connection part. + re-resolve connection state fresh each call (it changes when a user connects). Split keys or + short TTL (e.g., 30–60s) for the connection part.docs/design/agent-workflows/projects/tool-discovery/status.md (1)
59-60: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winClarify tie-breaking rule for multiple active connections.
The risk notes multiple connections per toolkit per project are possible. Specify the selection priority (e.g., most-recently-created, first-active, specific connection ID) in the design or plan so Phase 2 implementers don't guess.
- resolving the slug. + resolving the slug (e.g., prefer the most-recently-authenticated active connection).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 809f987c-e56b-46b2-a991-2d8476ea91ee
📒 Files selected for processing (7)
docs/design/agent-workflows/projects/tool-discovery/README.mddocs/design/agent-workflows/projects/tool-discovery/context.mddocs/design/agent-workflows/projects/tool-discovery/design.mddocs/design/agent-workflows/projects/tool-discovery/plan.mddocs/design/agent-workflows/projects/tool-discovery/research.mddocs/design/agent-workflows/projects/tool-discovery/status.mddocs/design/agent-workflows/projects/tool-discovery/use-case-walkthrough.md
aae9788 to
9c0237a
Compare
80ee74c to
20f6636
Compare
9c0237a to
b3226c5
Compare
Address Mahmoud's round-2 comments + CodeRabbit: - reference input_schema from the workflow's revision.schemas.inputs (messages via x-ag-type-ref); output schemas deferred - permissions uniform across all tool types (not special-cased on the call path) - platform-op catalog mirrors the reserved tools.agenta.* pattern (#4884 find_capabilities) + evaluators catalog, not platform_catalog.py wholesale - schema sourcing standardized on the in-process CATALOG_TYPES catalog (fixes the openapi.json inconsistency) - merge order/organization framed as the orchestrator's call
b3226c5 to
b871014
Compare
Planning workspace for find_capabilities: an agent-facing tool that wraps Composio's COMPOSIO_SEARCH_TOOLS to turn natural-language use cases into a wired set of Agenta tools plus a connection plan in one call, translated to Agenta concepts. Verified the endpoint, schemas, and per-project connection state (user_id == project_id) live. Design only, no runtime change. Claude-Session: https://claude.ai/code/session_01QCZZZawwY95v8gXiTQBgZp
|
|
||
| return ToolCallResponse(call=result) | ||
|
|
||
| async def _call_agenta_tool( |
There was a problem hiding this comment.
🤖 The AI agent says: This is the reserved-tool dispatch. call_tool routes any tools.agenta.* call here by prefix, so the reserved tool stays out of Composio's 5-segment namespace. v1 handles only find_capabilities and 404s anything else.
There was a problem hiding this comment.
review with codex on alignement with best practices and other places in the code
There was a problem hiding this comment.
and address if strong opinion
There was a problem hiding this comment.
🤖 The AI agent says: Done. Reviewed the reserved-tool dispatch with Codex (xhigh). Verdict: the prefix if-ladder in call_tool (workflow / agenta / gateway) is fine and consistent. It is a single tool-execute ingress, and there is no competing dispatch pattern elsewhere in the FastAPI routers to mirror. The one must-fix it raised was permission placement, addressed below.
There was a problem hiding this comment.
🤖 The AI agent says: Addressed. Codex's strong opinion was that the permission policy belongs at the call_tool dispatch boundary, not only inside the private handler. Fixed in 2df7029e: the tools.agenta.* branch in call_tool now requires VIEW_TOOLS on top of the outer RUN_TOOLS before dispatching, with an auth-split regression test. I also applied its anti-drift nit, deriving AGENTA_TOOL_CALL_REF_PREFIX from ToolProviderKind.AGENTA. Two nice-to-haves are deferred: a reserved-op registry (premature for one op), and unifying the /discover validator with the reserved-tool parser (their input handling differs on purpose, /discover rejects a scalar string with 422 while the reserved tool coerces a bare string to one use case).
| return out | ||
|
|
||
|
|
||
| def translate_search_result( |
There was a problem hiding this comment.
🤖 The AI agent says: This is the Composio→Agenta translation. Pure functions turn a raw Composio search into the native contract: tools as integration.action, connection state, and structured guidance. No provider slugs leak to the agent. This is the load-bearing mapping to review.
There was a problem hiding this comment.
we need some testing of this with real credential (ask parent agent) and creation of tests that makes sure that covers this well.
There was a problem hiding this comment.
🤖 The AI agent says: Split into two. (1) Real-credential testing: handed to the orchestrator's e2e pass, which runs find_capabilities against a project with a live Composio key and captures a replay fixture (agent-replay-test); the live call needs creds this step does not hold. (2) Translation test coverage: it is unit-covered in test_discovery.py (the Composio to Agenta contract, the three connection states, slug split, guidance rewrite, alternatives cap, trigger detection, and an end-to-end run over the recorded fixture). This round adds the auth-split test and non-dict-envelope cases. 77 tests pass.
| # Discovery — semantic tool search (COMPOSIO_SEARCH_TOOLS) | ||
| # ----------------------------------------------------------------------- | ||
|
|
||
| async def search_capabilities( |
There was a problem hiding this comment.
🤖 The AI agent says: This is the Composio adapter call. One COMPOSIO_SEARCH_TOOLS request returns matched tools, alternatives, inline schemas, and connection state. Agenta passes str(project_id) as the Composio user, so the state reflects the calling project.
| description: Use find_capabilities to discover the right Agenta tools for an agent you are building, report what each integration needs to connect, and wire the tools into the new agent's config. Use when a setup/builder agent must turn a plain-language task ("post to Slack and open GitHub issues") into attached, connected, ready-to-run tools. | ||
| --- | ||
|
|
||
| # Discover and wire tools with `find_capabilities` |
There was a problem hiding this comment.
🤖 The AI agent says: This is the discover-and-wire-tools skill, the agent-facing loop. It walks a setup agent from a plain-language task to attached, connected, ready-to-run tools (discover → read → connect → create agent). Check the steps are clear enough to follow unaided.
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (3)
docs/design/agent-workflows/projects/tool-discovery/research.md (1)
10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd language specifiers to fenced code blocks for better markdown rendering.
The pseudocode and data-structure blocks will render more consistently with explicit language tags (e.g.
json,http,text). This is optional hygiene for design docs.Also applies to: 32-32, 43-43, 57-57, 72-72, 79-79, 90-90
docs/design/agent-workflows/projects/tool-discovery/use-case-walkthrough.md (1)
20-20: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd language specifiers to fenced code blocks.
The HTTP request and JSON body blocks will render with better syntax highlighting using
httpandjsontags respectively.Also applies to: 49-49
api/oss/src/core/tools/dtos.py (1)
280-288: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winType the create-connection payload explicitly.
ConnectAffordance.bodyhas a fixed shape, but exposing it asDict[str, Any]weakens the discovery contract and makes the service return a raw nested dict. This should be modeled with named DTOs like the rest of the response.Proposed refactor
+class ConnectAffordanceConnection(BaseModel): + provider_key: str + integration_key: str + slug: str + + +class ConnectAffordanceBody(BaseModel): + connection: ConnectAffordanceConnection + + class ConnectAffordance(BaseModel): endpoint: str = "POST /tools/connections/" - body: Dict[str, Any] + body: ConnectAffordanceBodyAs per coding guidelines, "Do not return raw dicts or tuples from service methods or clients; define named DTOs in core/{domain}/dtos.py instead."
Source: Coding guidelines
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a3e98d46-7495-49af-89d2-ec429890c4cc
📒 Files selected for processing (23)
api/oss/src/apis/fastapi/tools/models.pyapi/oss/src/apis/fastapi/tools/router.pyapi/oss/src/core/tools/discovery.pyapi/oss/src/core/tools/dtos.pyapi/oss/src/core/tools/exceptions.pyapi/oss/src/core/tools/providers/composio/adapter.pyapi/oss/src/core/tools/providers/composio/dtos.pyapi/oss/src/core/tools/service.pyapi/oss/tests/manual/tools/tools.httpapi/oss/tests/pytest/unit/tools/fixtures/composio_search_tools.jsonapi/oss/tests/pytest/unit/tools/test_discovery.pydocs/design/agent-workflows/documentation/tools.mddocs/design/agent-workflows/interfaces/README.mddocs/design/agent-workflows/interfaces/cross-service/runner-to-tool-callback.mddocs/design/agent-workflows/interfaces/in-service/tool-models-and-resolution.mddocs/design/agent-workflows/projects/tool-discovery/README.mddocs/design/agent-workflows/projects/tool-discovery/context.mddocs/design/agent-workflows/projects/tool-discovery/design.mddocs/design/agent-workflows/projects/tool-discovery/plan.mddocs/design/agent-workflows/projects/tool-discovery/research.mddocs/design/agent-workflows/projects/tool-discovery/skills/discover-and-wire-tools/SKILL.mddocs/design/agent-workflows/projects/tool-discovery/status.mddocs/design/agent-workflows/projects/tool-discovery/use-case-walkthrough.md
✅ Files skipped from review due to trivial changes (4)
- api/oss/tests/pytest/unit/tools/fixtures/composio_search_tools.json
- docs/design/agent-workflows/interfaces/README.md
- docs/design/agent-workflows/interfaces/in-service/tool-models-and-resolution.md
- docs/design/agent-workflows/documentation/tools.md
…nslation, cache) Composio semantic-search adapter (search_capabilities) + Agenta-native translation (core/tools/discovery.py), connection-state reporting, structured guidance, v1 action-only scope with a trigger note (D5), and the D6 cache split (cache the tool/schema half, recompute connection state fresh). Recorded-fixture replay test + the setup-agent skill. Phase 2 (POST /tools/discover endpoint + reserved tools.agenta.find_capabilities) deferred behind router.py/models.py. Claude-Session: https://claude.ai/code/session_01GYo3UEfvsZpncagqb28Mbc
…rved tool route) Adds the project-scoped POST /tools/discover endpoint (CapabilitiesQuery -> ToolsService.discover_capabilities -> CapabilitiesResult; DiscoveryUnsupportedError -> 422) and the server side of the reserved tools.agenta.find_capabilities tool: /tools/call routes the tools.agenta. prefix to _call_agenta_tool (out of the Composio 5-segment namespace). The canonical reserved-tool spec lives in core/tools/discovery.py. Docs synced (tools.md, interface inventory, manual http). Stacked on feat/agent-embedref-tools: the router dispatch branch sits on the workflow.* routing committed there. The SDK-side declaration/resolution (emitting the CallbackToolSpec for the reserved tool) is deferred to the direct-call-tools platform-op seam; the runner is unchanged (forwards the call_ref opaquely). Claude-Session: https://claude.ai/code/session_01GYo3UEfvsZpncagqb28Mbc
485b8b2 to
7cdaa0b
Compare
|
🤖 The AI agent says: Addressed the review on head Fixed (4 real findings + 1 quick win):
Deferred: the Eight new tests cover the fixes. The tools suite is green (74 passed) and ruff is clean. @coderabbitai review |
|
I’ll re-review the latest changes on head If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! ✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 5
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a30d433f-4337-41fa-b908-1c40d19d31fa
📒 Files selected for processing (20)
api/oss/src/apis/fastapi/tools/models.pyapi/oss/src/apis/fastapi/tools/router.pyapi/oss/src/core/tools/discovery.pyapi/oss/src/core/tools/dtos.pyapi/oss/src/core/tools/exceptions.pyapi/oss/src/core/tools/providers/composio/adapter.pyapi/oss/src/core/tools/providers/composio/dtos.pyapi/oss/src/core/tools/service.pyapi/oss/tests/manual/tools/tools.httpapi/oss/tests/pytest/unit/tools/fixtures/composio_search_tools.jsonapi/oss/tests/pytest/unit/tools/test_discovery.pydocs/design/agent-workflows/documentation/tools.mddocs/design/agent-workflows/interfaces/README.mddocs/design/agent-workflows/interfaces/cross-service/runner-to-tool-callback.mddocs/design/agent-workflows/interfaces/in-service/tool-models-and-resolution.mddocs/design/agent-workflows/projects/tool-discovery/README.mddocs/design/agent-workflows/projects/tool-discovery/design.mddocs/design/agent-workflows/projects/tool-discovery/plan.mddocs/design/agent-workflows/projects/tool-discovery/skills/discover-and-wire-tools/SKILL.mddocs/design/agent-workflows/projects/tool-discovery/status.md
✅ Files skipped from review due to trivial changes (6)
- api/oss/tests/pytest/unit/tools/fixtures/composio_search_tools.json
- docs/design/agent-workflows/interfaces/in-service/tool-models-and-resolution.md
- docs/design/agent-workflows/interfaces/README.md
- docs/design/agent-workflows/interfaces/cross-service/runner-to-tool-callback.md
- docs/design/agent-workflows/projects/tool-discovery/design.md
- docs/design/agent-workflows/documentation/tools.md
🚧 Files skipped from review as they are similar to previous changes (8)
- api/oss/tests/manual/tools/tools.http
- api/oss/src/apis/fastapi/tools/models.py
- api/oss/src/core/tools/exceptions.py
- api/oss/src/core/tools/providers/composio/dtos.py
- api/oss/src/core/tools/dtos.py
- api/oss/src/core/tools/discovery.py
- api/oss/src/core/tools/service.py
- api/oss/tests/pytest/unit/tools/test_discovery.py
mmabrouk
left a comment
There was a problem hiding this comment.
would lgtm after addressing the comments by me and coderabbit. if well tested then feel free to merge
…e guard, doc sync Address PR #4884 review (Mahmoud + CodeRabbit + Codex xhigh): - Gate the reserved tools.agenta.* branch in call_tool with VIEW_TOOLS at the dispatch boundary (was RUN_TOOLS-only); discovery exposes per-project connection state. Add an auth-split regression test. - Adapter: reject a non-object COMPOSIO_SEARCH_TOOLS envelope as AdapterError instead of letting .get() raise AttributeError (500). Cover with non-dict envelope cases. - Derive AGENTA_TOOL_CALL_REF_PREFIX from ToolProviderKind.AGENTA (anti-drift). - Sync stale status banner / Phase headings / D1 in the project docs; add a find_capabilities availability caveat to the discover-and-wire-tools skill. Claude-Session: https://claude.ai/code/session_01QCZZZawwY95v8gXiTQBgZp
|
🤖 The AI agent says: Review pass on this PR. Renamed it and rewrote the description so it reads as the implementation it is (it was titled What changed this pass (commit
|
| Comment | Outcome |
|---|---|
| Mahmoud: add a skill (not agents.md) + subagent setup test | Skill ships in the PR; live subagent test handed to orchestrator e2e |
Mahmoud: /debug-local exploratory QA |
Deferred to orchestrator e2e (needs the live stack) |
| Mahmoud: review dispatch with Codex, address if strong | Done; VIEW_TOOLS-at-boundary applied (see thread) |
| Mahmoud: test the translation with real credentials | Real-cred run is orchestrator e2e; translation is unit-covered, more tests added |
| CodeRabbit: VIEW_TOOLS / envelope guard / 3 doc staleness | All fixed in 2df7029e |
CodeRabbit: /discover count+payload envelope |
Withdrawn by CodeRabbit (shared contract, deferred) |
design-interfaces review
Ran the design-interfaces skill over the /tools/discover request and the CapabilitiesResult response. The contract is role-aligned: top-level sections read as capabilities / connections / guidance / ready / notes, lists are plural maps, no secret leaks into the contract (connection state is a slug plus an enum, not a credential), and the connect affordance is scoped under the integration it connects. No low-risk in-file change is needed. One follow-up worth noting (a contract change, not forced now): DiscoveredTool.provider_action carries the raw Composio slug as a debug field. It is documented as opaque and debug-only, but it is a mild implementation-detail leak, so dropping it from the response is a candidate cleanup for a later slice.
Deferred (follow-ups, not blockers)
- SDK-side reserved-tool declaration so an agent config surfaces
find_capabilitiesto the model (rides the direct-call-tools platform-op seam, Workstream A). - Codex P2s: a reserved-op registry (premature for one op) and unifying the
/discovervalidator with the reserved-tool parser (their input handling differs by design). - Live e2e plus a replay-fixture upgrade with a real Composio key.
Stack note
This is the base of the Workstream A stack, so re-pushing it rebased the three lanes above. All four are re-pushed and remote matches: docs/tool-discovery-find-capabilities (2df7029e), feat/direct-call-tools (ac471ec8), feat/direct-call-tools-dispatch (2bb2c6a6), feat/direct-call-tools-runcontext (85f4db7a). The rebase preserved the already-merged review fixes.
What I need: a re-review of 2df7029e (the VIEW_TOOLS gate, the envelope guard, and the doc sync). Gates are green: ruff format and ruff check clean, and 77 tests pass in oss/tests/pytest/unit/tools/. I am not merging from here; the orchestrator merges after the live e2e pass.
|
@coderabbitai review |
✅ Action performedReview finished.
|
Context
Building an agent that spans a few SaaS tools (say a Slack bot that searches GitHub, files an issue, and replies in Slack) currently takes about 20 sequential, slug-guessing API calls just to discover the right tools and check their connections. Every step depends on the previous one, and the caller has to stitch three concerns by hand: which action, does a connection exist, and what is its input schema.
This PR collapses that discovery into one call and returns the result in Agenta concepts, so the agent never sees Composio. It adds
POST /tools/discoverfor setup code and a reserved, agent-facing tooltools.agenta.find_capabilitiesfor an agent that is wiring its own tools. Both wrap Composio'sCOMPOSIO_SEARCH_TOOLSmeta-tool, which already does the semantic search and returns, in one call, the matched tools, alternatives, input schemas, an execution plan, pitfalls, and per-user connection state. The load-bearing mapping is that Composio'suser_idis the Agentaproject_id, so the connection state it returns is the calling project's real state.Changes
POST /tools/discover(requiresVIEW_TOOLS):CapabilitiesQuerytoToolsService.discover_capabilitiestoCapabilitiesResult. An unsupported provider returns 422. Project scope comes from caller auth, not the body.tools.agenta.find_capabilities.call_toolroutes anytools.agenta.*call_ref to_call_agenta_toolby prefix, so the reserved tool stays out of Composio's 5-segmenttools.{provider}.{integration}.{action}.{connection}namespace. v1 handlesfind_capabilitiesand 404s any other reserved op.ComposioToolsAdapter.search_capabilities: oneCOMPOSIO_SEARCH_TOOLSrequest. A tool-level failure, missing data, or a malformed envelope raisesAdapterError(surfaced as 424) instead of a silent empty result.core/tools/discovery.py: tools becomeintegration.action, connection state becomesready/needs_auth/needs_input, and guidance is mapped to the same Agenta names. No provider slugs leak to the agent.discover-and-wire-toolsskill (the setup-agent loop: discover, read, connect, create) and the project design docs underdocs/design/agent-workflows/projects/tool-discovery/.Scope / risk
find_capabilitiesis callable today two ways:POST /tools/discover, andPOST /tools/callwith call_reftools.agenta.find_capabilities. The SDK-side reserved-tool declaration (so an agent config surfaces the tool to the model automatically) lands in Workstream A Phase 3b, on the direct-call-tools platform-op seam. The runner forwards the call_ref opaquely, so it needs no change.VIEW_TOOLSin addition to the outerRUN_TOOLS, because discovery exposes per-project connection state.big-agentsto [feat] Tool discovery: POST /tools/discover + reserved find_capabilities tool #4884 to [feat] Direct-call tools — Phase 1: call descriptor on the resolved spec #4889 to [feat] Direct-call tools — Phase 2: sidecar dispatch branch #4891 to [feat] Direct-call tools — Phase 3a: run-context delivery + bind #4892.How to QA
Prerequisites: local dev stack (
run.sh --oss --devor--ee --dev). For a live run, the calling project needs a Composio provider key in its vault. The unit tests need none; they replay a recordedCOMPOSIO_SEARCH_TOOLSresponse.Steps (offline, no credentials):
api/, run the discovery unit suite (command below).Steps (live, needs a Composio key):
Expected result: a
CapabilitiesResultwith onecapabilities[]entry per use case (best-matchtoolasintegration.actionplus itsinput_schema), a dedupedconnections[]list with each integration's state,guidance(plan steps and pitfalls), andreadytrue only when every primary connection is ready. No raw Composio slug appears except the clearly-labelledprovider_actiondebug field.Automated tests:
Manual request samples live in
api/oss/tests/manual/tools/tools.http.Edge cases: a bare-string
use_casesmust be rejected (422 on/discover) or treated as one use case (reserved tool), never iterated character by character. A use case with no primary match keepsreadyfalse. A trigger-shaped use case ("when a new email arrives") returns a note, not a tool.Interface reference
Request (
POST /tools/discover, bodyCapabilitiesQuery):{ "use_cases": ["create a github issue", "send a slack message"], // required, non-empty "provider": "composio", // optional, default "composio" "limit_alternatives": 3 // optional, default 3, >= 0 }Response (
CapabilitiesResult, returned by/discoverand as the reserved tool's result):{ "capabilities": [ { "use_case": "create a github issue", "integration": "github", "tool": { "type": "gateway", "provider": "composio", "integration": "github", "action": "CREATE_AN_ISSUE", "connection": "github-main", // set only when state == ready "input_schema": { /* JSON schema */ }, "provider_action": "GITHUB_CREATE_AN_ISSUE" // opaque debug field, not the interface }, "alternatives": [ /* DiscoveredAlternative[] */ ], "connection": { "state": "ready", "slug": "github-main" }, "note": null } ], "connections": [ { "integration": "github", "state": "ready", "slug": "github-main" }, { "integration": "slack", "state": "needs_auth", "connect": { "endpoint": "POST /tools/connections/", "body": { /* ... */ } } } ], "guidance": { "plan_steps": ["..."], "pitfalls": ["..."] }, "ready": false, "notes": [] }Reserved tool call_ref:
tools.agenta.find_capabilities. An agent calls it throughPOST /tools/call(the runner forwards the call_ref opaquely); the router routes it by thetools.agenta.prefix to the samediscover_capabilitiesservice. Its input schema mirrors the request above withuse_casesrequired.https://claude.ai/code/session_01QCZZZawwY95v8gXiTQBgZp