Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/server/src/mcp/toolInstructions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** Prism guidance shared by every provider runtime. */
export const T3_CODE_TOOL_USE_INSTRUCTIONS = `<t3_code_tool_use>
Use the t3-code MCP tools for visible agent work. Delegate children with delegate_task (role and optional lane/prismRole); launch explicitly requested top-level work with t3_thread_launch. Prism chooses provider, model and effort unless the user supplies an explicit target/modelSelection. Never substitute shell agent CLIs.
Use task_status/task_cancel for delegated tasks and t3_thread_read/t3_thread_wait/t3_thread_interrupt for ordinary threads. Each review round is a new delegate_task call with its full brief and prior findings. Use t3_pending_request_respond only within its advertised permissions.
Use task_status/task_cancel for delegated tasks and t3_thread_read/t3_thread_wait/t3_thread_interrupt for ordinary threads. Each review round is a new delegate_task call with its full brief and prior findings. To continue the same job after a stop or a cleared blocker, t3_thread_send to its childThreadId and t3_thread_wait on it; follow-ups do not wake you. Use t3_pending_request_respond only within its advertised permissions.
Machine recovery is automatic: usage limits wait for reset; retryable provider failures receive at most one persisted retry on the same provider and model. Stop and retirement cancel recovery. Completed or silent work stays the parent's decision; optional prismRole retry/escalation requests a new kit when appropriate.
</t3_code_tool_use>`;
4 changes: 4 additions & 0 deletions apps/server/src/mcp/toolkits/orchestrator/tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ describe("orchestrator MCP tool guidance", () => {
OrchestratorToolkit.tools.t3_thread_send.description ?? "",
"Do not use a delegated task's childThreadId to start another review round",
);
assert.include(
OrchestratorToolkit.tools.t3_thread_send.description ?? "",
"To continue the same delegated job after it stopped",
);
assert.include(
OrchestratorToolkit.tools.task_cancel.description ?? "",
"This includes later child-thread runs, even after the task is terminal",
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/mcp/toolkits/orchestrator/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ export const ThreadUpdateTool = Tool.make("t3_thread_update", {

const ThreadSendTool = Tool.make("t3_thread_send", {
description:
"Send a message to any T3 thread in this environment. The target cannot have broader permission modes than the caller. Do not use a delegated task's childThreadId to start another review round here; use delegate_task with the full review context and a new clientRequestId for that round. Thread messages do not create a new delegated task or reopen a completed task. Spectrum transcript threads return runId=null, status=idle and delivery=transcript; they never start a provider on the transcript thread. mode='auto' starts an idle thread, steers a fully active turn, or queues behind a turn that is not yet steerable. Use queue for a separate follow-up turn, steer for an in-flight update, or restart to interrupt-and-restart the active turn. clientRequestId makes retries idempotent.",
"Send a message to any T3 thread in this environment. The target cannot have broader permission modes than the caller. Do not use a delegated task's childThreadId to start another review round here; use delegate_task with the full review context and a new clientRequestId for that round. To continue the same delegated job after it stopped, send here to its childThreadId and wait with t3_thread_wait; the result appears in task_status latestTerminal* and does not wake the parent. Thread messages do not create a new delegated task or reopen a completed task. Spectrum transcript threads return runId=null, status=idle and delivery=transcript; they never start a provider on the transcript thread. mode='auto' starts an idle thread, steers a fully active turn, or queues behind a turn that is not yet steerable. Use queue for a separate follow-up turn, steer for an in-flight update, or restart to interrupt-and-restart the active turn. clientRequestId makes retries idempotent.",
parameters: OrchestratorMcpThreadSendInput,
success: OrchestratorMcpThreadSendResult,
failure: OrchestratorMcpFailure,
Expand Down
2 changes: 2 additions & 0 deletions apps/server/src/provider/T3OrchestrationInstructions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ describe("T3 orchestration provider instructions", () => {
T3_CODE_ORCHESTRATION_INSTRUCTIONS,
"Do not use `t3_thread_send` on `childThreadId`",
);
assert.include(T3_CODE_ORCHESTRATION_INSTRUCTIONS, "To continue the same delegated job");
assert.include(T3_CODE_ORCHESTRATION_INSTRUCTIONS, "does not wake you");
});

it("documents structured schedules instead of JSON strings", () => {
Expand Down
1 change: 1 addition & 0 deletions apps/server/src/provider/T3OrchestrationInstructions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The \`t3-code\` MCP server provides app-owned orchestration. Treat these concept
- A delegated task/subagent is child work owned by the current thread. Use \`delegate_task\` so Prism selects the provider, model and effort from the configured role kit and capacity. Omit \`target\` unless the user explicitly chose a provider/model; an explicit target wins over Prism. Upstream role labels map to kits: implementation/test/general to worker, review to reviewer, research/design to planner. Use optional \`lane\` for worker difficulty and \`prismRole\` for an explicit kit. Retain each returned \`taskId\`, and use \`task_status\` or \`task_cancel\` to manage it. The returned \`childThreadId\` is backing storage, not the target for starting another delegated review round. Do not start shell agent CLIs or native subagents for work that belongs in visible T3 threads.
- \`t3_thread_launch\` and \`create_threads\` create ordinary top-level T3 conversations. \`t3_thread_launch\` uses Prism and accepts optional \`prismRole\` (including dispatcher or promachos) and \`lane\`; an explicit \`modelSelection\` wins. Use them only when the user explicitly asks for separate/new/top-level threads or conversations. Never use them merely because the user said "subagent" or requested parallel delegated work.
- For every T3 delegated review round, call \`delegate_task\` again. Include the original brief, prior findings, responses, and unresolved objections in each new task prompt. Track each round by its own \`taskId\`. Use a distinct \`clientRequestId\` per round, stable across retries of that round. Do not use \`t3_thread_send\` on \`childThreadId\` to continue a delegated review.
- To continue the same delegated job after it stopped on a blocker or question that has since been resolved (the user answered, granted access, or cleared the blocker), send the follow-up to that task's \`childThreadId\` with \`t3_thread_send\` and wait on it with \`t3_thread_wait\`; the child keeps its context. The follow-up result appears in \`task_status\` as \`latestTerminal*\` and does not wake you. Start a new \`delegate_task\` only for independent work, such as a fresh review round or a different job.
- \`schedule_task\` creates persistent recurring work in the app scheduler. Pass \`schedule\` as a structured object, never as JSON text: \`{"type":"interval","everyMs":3600000}\` for an interval, or \`{"type":"fixed_time","timeOfDay":"09:00","weekdays":[1,2,3,4,5]}\` for a wall-clock schedule, or \`{"type":"webhook"}\` to run on each request to the returned \`webhookUrl\` (the run sees the request only through \`{{body.path}}\`-style placeholders in the prompt). By default runs return to the current thread, which suits orchestrating: each trigger arrives here and you delegate or dedupe; set \`bindToCurrentThread=false\` only when the user wants a fresh thread for every run. After scheduling a timer, report the returned cadence and next run time; for a webhook, report its \`webhookUrl\`, or say T3 Connect remote access is needed if it is missing.
- When you need a secret from the user (a token, API key, or webhook signing secret), call \`request_secret\` so they enter it privately, then pass the returned \`secretRef\` to the tool that needs it, e.g. \`signature.secretRef\` on a webhook task for a sender that signs requests such as GitHub. A \`secretRef\` works once. Never ask for a secret in chat, never invent one, and never repeat one.
- To mention another thread to the user, link it as \`[title](t3-thread://v1/<threadId>)\` with its exact \`threadId\`, not URL-encoded. T3 Code opens the thread in the app and shows its current title.
Expand Down
Loading