Stamp parent_tool_slug + parent_log_id on child tool-execution logs so a meta tool's log_id joins to every tool it fanned out to. Surfaced on GET /api/v3.1/logs/tool_execution/{id} as parent: { log_id, tool_slug } | null.
| Parent meta tool | parent.tool_slug on the child log | parent.log_id on the child log |
|---|---|---|
| Multi-execute fan-out | COMPOSIO_MULTI_EXECUTE_TOOL | The multi-execute call's own log_id |
Workbench run_composio_tool callback | COMPOSIO_REMOTE_WORKBENCH | The workbench call's own log_id |
Surfaced via GET /api/v3.1/logs/tool_execution/{id} → parent: { log_id, tool_slug } | null. Stored in tool_execution_logs.sessionInfo JSON as parent_tool_slug + parent_log_id.
Single canonical type ToolExecutionParent = { tool_slug: string; log_id: string } (apps/apollo/src/lib/logger/session_info.ts). Two parents wired today via META_TOOLS_WITH_CHILDREN in execute_tool.ts:
COMPOSIO_MULTI_EXECUTE_TOOL — in-process fan-out. MultiExecuteToolAction.execute calls executeToolForSessionExecute directly (not via the RPC wrapper) and passes parent as a sibling arg, unreachable from any HTTP body. Fully trusted.COMPOSIO_REMOTE_WORKBENCH — sandbox-side run_composio_tool callbacks. RemoteWorkbenchAction.execute injects COMPOSIO_PARENT_TOOL_SLUG + COMPOSIO_PARENT_LOG_ID as per-cell env vars on executeCode(). The toolrouter_run_composio_tool.py helper reads them and POSTs parent: { tool_slug, log_id } in the HTTP body. Best-effort trust — the sandbox is LLM-controlled; a misbehaving cell could forge parent. Forgery is bounded to the project's own log space (logs are project-scoped) → no cross-tenant risk. Redis-tracked server-verified linkage is recorded as follow-up.executeToolForSessionExecute)| Source | Result |
|---|---|
parent sibling arg (in-process) | trusted |
body + sandbox auth (x-session-access-key) | best-effort trusted |
| body + public API key | dropped + warn log |
Two names internally, both typed ToolExecutionParent:
parent — the parent of the current execution (everywhere: wire schema field, ExecuteToolParams, ExecutionParams, RPC sibling arg, trust-gate local, enrichSessionInfo arg, sandbox HTTP body key).childParent — derived locally when this execution is a meta tool; passed to dispatcher functions that hand off to MultiExecuteToolAction.execute / RemoteWorkbenchAction.execute.Wire field on ExecuteToolForSessionRequestSchema is parent (not _parent) with .openapi({ 'x-internal': true }) — same hidden-field pattern as CategoriesField on session create.
generateLogId() is hoisted in executeTool so the parent log_id is known before fan-out; the same id is still used by the single insertToolExecutionLogs call at the bottom.
No DB migration — sessionInfo is a JSON column.
src/lib/logger/session_info.unit.test.ts — schema parse + standardize accept parent_tool_slug / parent_log_id (snake + camelCase).src/lib/tool_execution/util.test.ts — enrichSessionInfo stamps parent when provided.src/lib/toolRouterV2/features/execution/__tests__/execute_parent_schema.unit.test.ts — parent zod schema accepted/validated.src/lib/composio_actions/actions/toolRouter/multiExecuteTool.test.ts — mocks updated for executeToolForSessionExecute direct call.vitest run src/lib/tool_execution src/lib/logger src/lib/openapi src/lib/composio_actions/actions/toolRouter/__tests__.
apollo-git-zen-tool-log-parent-5sdd6o.preview.composio.dev)All scenarios verified against the cleaned-up code (commits c74c39c1a4 + 6c7029fdb5). Log IDs for cross-check in ClickHouse:
| # | Scenario | Parent log_id | Child log_id | Expected parent | Got |
|---|---|---|---|---|---|
| T1 | Positive multi-execute (success child) | log_Mp4TykgOHsqK | log_vMM791rFQgBJ | {log_id: log_Mp4TykgOHsqK, tool_slug: MULTI_EXECUTE_TOOL} | ✅ matches |
| T2 | Negative multi-execute (child invalid args) | log_fGHNfyfL6OLI | log_btmdo6htuLx- | {log_id: log_fGHNfyfL6OLI, tool_slug: MULTI_EXECUTE_TOOL} | ✅ matches |
| T3 | Direct execute in tool-router session (no meta wrapper) | — | log_sTzStUDhbpos | null | ✅ null |
| T4 | Non-toolrouter /api/v3.1/tools/execute/{slug} (critical regression check) | — | log_HLWvFjBPJphf | null | ✅ null |
| T5 | Workbench → run_composio_tool (sandbox-authed callback)* | log_zQd8Qc-rWuWa | log_WmjsNVI3spdW | {log_id: log_zQd8Qc-rWuWa, tool_slug: REMOTE_WORKBENCH} | ✅ matches |
| T6 | Forged parent from public API key | — | log_yDs_d3S_7a8R | null (trust gate drops it) | ✅ null |
* T5 requires overriding BACKEND_URL inside the cell to route the sandbox callback through the preview deployment (default BACKEND_URL points at master).
Two passes:
parent (initial impl had no gate) → fixed with parent sibling arg + body gate. Verified by T6.parent is still LLM-forgeable → documented as best-effort (bounded to project's own log space). Redis-verified linkage recorded as follow-up.pnpm check-types: clean.pnpm lint: clean (one pre-existing warning in unrelated file).pnpm format:check: clean.🤖 Generated with Claude Code
Based on git blame analysis of 11 file(s):
| Contributor | Contribution | Files |
|---|---|---|
| Zen | 26% | 11 |
| abir-taheer | 24% | 6 |
| Dhawal Upadhyay | 24% | 7 |
| Himanshu Dixit | 7% | 7 |
| lingalarahul7 | 5% | 5 |
Based on git history, Zen or abir-taheer would be good reviewer(s) for this PR.
🤖 Based on git blame with recency weighting (recent edits count more).
:x: Patch coverage is 82.95455% with 15 lines in your changes missing coverage. Please review.
| Flag | Coverage Δ | |
|---|---|---|
| e2e-tests | 5.79% <2.27%> (+0.03%) | :arrow_up: |
| self-hosted-tests | 5.61% <13.63%> (+0.04%) | :arrow_up: |
| thermos-service-isolation-tests | ? | |
| thermos-unit-tests | ? | |
| unit-tests | 58.78% <82.55%> (+0.52%) | :arrow_up: |
Flags with carried forward coverage won't be shown. Click here to find out more.
| Files with missing lines | Coverage Δ | |
|---|---|---|
| ...sio_actions/actions/toolRouter/multiExecuteTool.ts | 86.45% <100.00%> (+0.07%) | :arrow_up: |
| ...osio_actions/actions/toolRouter/remoteWorkbench.ts | 85.06% <100.00%> (+0.27%) | :arrow_up: |
| apps/apollo/src/lib/logger/session_info.ts | 82.11% <100.00%> (+23.23%) | :arrow_up: |
| ...toolRouterV2/features/execution/executeMetaTool.ts | 82.01% <100.00%> (+0.15%) | :arrow_up: |
| ...o/src/lib/toolRouterV2/features/execution/index.ts | 100.00% <ø> (ø) | |
| apps/apollo/src/lib/toolRouterV2/index.ts |
... and 280 files with indirect coverage changes
100.00% <ø> (ø) |
| apps/apollo/src/lib/tool_execution/executable.ts | 52.00% <100.00%> (+0.32%) | :arrow_up: |
| apps/apollo/src/lib/tool_execution/util.ts | 98.59% <100.00%> (+0.05%) | :arrow_up: |
| ...s/apollo/src/lib/logger/unified-log-transformer.ts | 98.64% <85.71%> (-0.65%) | :arrow_down: |
| apps/apollo/src/lib/tool_execution/execute_tool.ts | 42.00% <88.23%> (+0.74%) | :arrow_up: |
| ... and 2 more |