From dea19988789597d091a74a55fb02c744cf224ce6 Mon Sep 17 00:00:00 2001 From: evilweasel <38261180+EvilWeasel@users.noreply.github.com> Date: Fri, 13 Nov 2026 15:47:20 +0100 Subject: [PATCH 1/2] fix(mcp): clarify delegation parent and result delivery --- apps/server/src/mcp/toolkits/orchestrator/tools.ts | 2 +- packages/contracts/src/orchestratorMcp.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/server/src/mcp/toolkits/orchestrator/tools.ts b/apps/server/src/mcp/toolkits/orchestrator/tools.ts index 53a808df30e96..2300546a5fd08 100644 --- a/apps/server/src/mcp/toolkits/orchestrator/tools.ts +++ b/apps/server/src/mcp/toolkits/orchestrator/tools.ts @@ -339,7 +339,7 @@ const ThreadUpdateTool = Tool.make("t3_thread_update", { const ThreadSendTool = Tool.make("t3_thread_send", { description: - "Send a message to any thread. The target cannot run with broader modes than yours. `mode:'auto'` starts an idle thread, steers a running turn, or queues. `queue`: new turn. `steer`: mid-turn update. `restart`: interrupt and restart. A send to a finished child thread starts a fresh task and returns its `taskId`. In your reply, name it as its `link` verbatim.", + "Message a thread; modes cannot exceed yours. `auto`: start idle, steer running, or queue. `queue`: new turn. `steer`: mid-turn update. `restart`: interrupt and restart. With `delegation`, `threadId` owns new work; results are published there; no automatic MCP caller resume. Continue a finished child without `delegation` for a fresh `taskId`; use `delegate_task` for caller-owned work. Use its `link` verbatim.", parameters: OrchestratorMcpThreadSendInput, success: OrchestratorMcpThreadSendResult, failure: OrchestratorMcpFailure, diff --git a/packages/contracts/src/orchestratorMcp.ts b/packages/contracts/src/orchestratorMcp.ts index 43e456e4ccb05..80cdbe2a2b2ef 100644 --- a/packages/contracts/src/orchestratorMcp.ts +++ b/packages/contracts/src/orchestratorMcp.ts @@ -589,7 +589,7 @@ export const OrchestratorMcpConversationDelegation = Schema.Struct({ interactionMode: Schema.optional(OrchestratorMcpInteractionMode), }).annotate({ description: - "Explicit independent work: admit a fresh real child immediately, even while this conversation has an active provider run. For a new destination worktree, set workspaceStrategy and explicitly select target.providerInstanceId and target.model; projectId selects the local destination. Use a stable clientRequestId. Follow-ups should target the existing task/child instead.", + "New independent child of threadId: results are published there; no automatic MCP caller resume. Omit delegation for follow-ups; for caller-owned work use delegate_task. For a new worktree set workspaceStrategy, target.providerInstanceId and target.model; projectId sets the local project. Use a stable clientRequestId.", }); export const OrchestratorMcpThreadSendInput = Schema.Struct({ From 7ad572a5efcf0ab5f163f6831df3311ab3c5e4dc Mon Sep 17 00:00:00 2001 From: evilweasel <38261180+EvilWeasel@users.noreply.github.com> Date: Fri, 13 Nov 2026 16:18:47 +0100 Subject: [PATCH 2/2] test(mcp): cover completed-child delegation ownership --- evals/mcp-tool-use/cases/orchestration.ndjson | 2 ++ 1 file changed, 2 insertions(+) diff --git a/evals/mcp-tool-use/cases/orchestration.ndjson b/evals/mcp-tool-use/cases/orchestration.ndjson index 7d2145c6214d5..9f6f297483ba4 100644 --- a/evals/mcp-tool-use/cases/orchestration.ndjson +++ b/evals/mcp-tool-use/cases/orchestration.ndjson @@ -40,3 +40,5 @@ {"id":"thread-reference-real-title","area":"orchestration","kind":"bad","pattern":"internal agent initials in user-facing status","experience":"The coordinator used internal U/V aliases instead of understandable thread names and links.","rule":"Name other threads with their actual title and returned canonical link.","privacy":"commit-safe","setup":{"role":"top","priorTurns":[{"role":"assistant","text":"Internal notes: U handles integration.","toolCalls":[{"tool":"t3_thread_read","input":{"threadId":"22222222-2222-4222-8222-222222222222"},"result":{"thread":{"threadId":"22222222-2222-4222-8222-222222222222","title":"Release integration","link":""},"items":[{"type":"assistant_message","text":"Source proof is ready."}]}}]}],"mocks":{"t3_thread_read":{"thread":{"threadId":"22222222-2222-4222-8222-222222222222","title":"Release integration","link":""}}}},"prompt":"Give me a short status of that assignment and make its responsible chat easy to open.","expect":{"textMust":["t3-thread://v2/11111111-1111-4111-8111-111111111111/22222222-2222-4222-8222-222222222222"],"textMustNot":["\\bU\\b","\\bV\\b"]},"maxSteps":3} {"id":"thread-reference-id-lookup","area":"orchestration","kind":"guard","pattern":"thread id has no human-readable reference","experience":"A status handoff contains only the other thread id.","rule":"Look up its title and canonical link once instead of inventing a name or link.","privacy":"commit-safe","setup":{"role":"top","context":"The task is waiting for the owner thread 22222222-2222-4222-8222-222222222222. Its title is not present in this context.","mocks":{"t3_thread_read":{"thread":{"threadId":"22222222-2222-4222-8222-222222222222","title":"Release integration","link":""},"items":[{"type":"assistant_message","text":"Waiting for verification."}]}}},"prompt":"Which chat owns this work? Give me its readable reference.","expect":{"calls":[{"tool":"t3_thread_read","args":{"threadId":"22222222-2222-4222-8222-222222222222"}}],"maxCalls":{"t3_thread_read":1},"textMust":["t3-thread://v2/11111111-1111-4111-8111-111111111111/22222222-2222-4222-8222-222222222222"],"textMustNot":["\\bU\\b","\\bV\\b"]},"maxSteps":3} {"id":"thread-reference-code-variables","area":"orchestration","kind":"control","pattern":"ordinary variable names are not agent aliases","experience":"Letters U and V occur as ordinary code variables.","rule":"Do not treat ordinary variables as references to other threads.","privacy":"commit-safe","setup":{"role":"top"},"prompt":"Explain this TypeScript expression in one sentence: const U = 2; const V = 3; const total = U + V; Do not run tools.","expect":{"notCalls":["t3_thread_read","t3_thread_list","t3_thread_send"],"textMust":["5"],"textMustNot":["t3-thread://"]},"maxSteps":1} +{"id":"completed-research-caller-owned-work","area":"orchestration","kind":"bad","pattern":"independent work is delegated under a completed research child instead of its caller","experience":"A coordinator sent independent implementation work to a completed research child with delegation, then waited in the caller for a result published under the research child.","privacy":"commit-safe","source":{"origin":"Maintainer-observed completed-child routing mistake, 2026-11-13","pullRequest":"https://github.com/morrowbyte/t3code/pull/151"},"setup":{"role":"top","context":"This conversation is 11111111-1111-4111-8111-111111111111. Its research child 22222222-2222-4222-8222-222222222222 has completed and reported a parser repair recommendation. No implementation work has started. The thread identities and completion state are already verified."},"prompt":"The research is finished. Start one new independent implementation child for its parser repair recommendation. I want the completion delivered back to this conversation, not owned by the finished research chat. Use the authorized codex instance and gpt-6.1-sol. Give it the brief \"Implement the parser repair and report focused validation.\" Report the returned task identity and end this turn after launching it.","expect":{"calls":[{"tool":"delegate_task","args":{"target.providerInstanceId":"codex","target.model":"gpt-6.1-sol"}}],"notCalls":["t3_thread_send","t3_thread_launch","create_threads","task_status"],"maxCalls":{"delegate_task":1},"endsTurnAfter":"delegate_task","textMust":["task-1"]},"notes":"Synthetic, anonymized replay of the observed ownership mistake. The API choice binds new work to the caller; no real child, result delivery or provider wakeup is executed by this fixture."} +{"id":"completed-research-ordinary-continuation","area":"orchestration","kind":"control","pattern":"an ordinary completed-child continuation is replaced by new independent child work","experience":"An ordinary clarification to a completed research child should continue that same child and retain its existing parent rather than create independent work under it.","privacy":"commit-safe","source":{"origin":"Ordinary-work control for the maintainer-observed completed-child routing mistake, 2026-11-13","pullRequest":"https://github.com/morrowbyte/t3code/pull/151"},"setup":{"role":"top","context":"This conversation is 11111111-1111-4111-8111-111111111111. Its research child 22222222-2222-4222-8222-222222222222 has completed and reported its research here. Its parent is this conversation. The thread identities and completion state are already verified.","mocks":{"t3_thread_send":{"threadId":"22222222-2222-4222-8222-222222222222","messageId":"message:clarification","runId":"run:clarification","taskId":"task:continued-research","status":"running","delivery":"started"}}},"prompt":"Continue that same finished research child with this clarification: \"Check the parser recommendation against the empty-input case and report back here.\" Keep its existing provider and model. This is a continuation of its research, not a new independent implementation task. Send the clarification once, report the returned task identity, and end this turn.","expect":{"calls":[{"tool":"t3_thread_send","args":{"threadId":"22222222-2222-4222-8222-222222222222"}}],"callsMustNot":[{"tool":"t3_thread_send","args":{"delegation":"~{"}}],"notCalls":["delegate_task","t3_thread_launch","create_threads","task_status"],"maxCalls":{"t3_thread_send":1},"endsTurnAfter":"t3_thread_send","textMust":["task:continued-research"]},"notes":"The existing partial argument matcher rejects any object-valued delegation field. The returned fresh task receipt is required in the final answer. This is a simulated normal send, not runtime delivery proof."}