Add parallel course correction agent with forced tool call

I want to add a new agent. But it's different from the rest. It runs in parallel to the main thread. on every inference:completed (either tool_use or or end_turn) it runs one forced tool call with gemini with the entire thread. The forced tool call is to a new tool we are adding called course_correct, course correct has a boolean field (if true we want to add a course correct), and an optional message to be sent to the agent to stear it. The message should be like a user message, but it should have some metadata so we can render it differently. You should use gemini 3 as the model. The system prompt should ask it to check whether the model has forgotten anything or whether the model is going too far off the plan (diverging) or too narrow (not doing enough) and then correct its course. Or whether anything was forgotten based on the AGENTS.md file (run lint, ...) We need to: 1. add the tool 2. add the logic to trigger the forced tool call (look at the handoff logic for this for how to force a tool call with a prompt) 3. Create a good system prompt for it (we want the custom system prompt, the messages from the original thread as markdown, which should hightlight the user messages and the AGENTS.md file read in). 4. Add the logic to send the user:message in the thread worker / thread delta based on the result. This should run in the background once an tool_use stop reason is here, so it completed with the rool results and it should be sent after the tool results have been added to the thread but before we send a new request. On stop reason end of turn, we run it and send it only if the user has not sent a message yet.

I'll help you add a course correction agent. Let me first explore the codebase to understand the relevant patterns.

Ran tool todo_write
Searched codebase
Searched codebase
Searched codebase

Let me read the key files to understand the patterns better:

Explored 3 files
Ran tool todo_write

Let me also check the thread structure to understand how user messages are added and look at an example tool definition:

Explored 2 files, 1 search

Let me also check the tool-service to understand the BaseToolSpec structure and look at the thread-delta for how user messages are added:

Explored 2 files, 1 search

Now let me look at thread-delta to see more about user messages and check the thread structure for ThreadUserMessage:

Explored 3 files

Now let me look at how runInferenceAndUpdateThread works and check when we can inject logic after tool results are added:

Explored 3 files, 1 search

Now I understand the structure better. Let me also look at the hooks system since it's used for end-turn handling:

Explored 2 files, 1 search

Now let me check the handoff tool definition to understand the pattern better:

Explored 1 file

Now I have a good understanding of the structure. Let me create the course correction agent. I'll start by creating a new file:

Explored 1 file
Ran tool todo_write

Let me check the thread-markdown.ts file and look at how to format threads as markdown:

Explored 1 file, 1 search

Now I have a good understanding. Let me create the course correction agent file:

Created course-correction.ts
+215
Ran tool todo_write

Now I need to integrate this into the thread-worker. Let me first understand the hooks schema better and then modify the thread-worker:

Explored 1 file

Now let me look at how InternalHooks is used and where we should add the course correction logic. Let me also check the thread-delta for adding a new delta type for course correction messages:

Explored 1 file

I see that the source field on user messages can be used to track where a message came from. Let me extend this to support course correction. Let me update the thread.ts to add a new source type:

Edited thread.ts
+11
-6

Now I need to integrate the course correction logic into the thread-worker. Let me look at the end of executeToolBatchesSequentially where inference is triggered:

Explored 1 file

Now let me understand where to add the course correction logic. I need to look at when tools complete and inference is triggered. Let me look at more of the tool:data handling:

Explored 1 file

Now I understand the flow. The course correction should run:

  1. After tool execution completes (before runInferenceAndUpdateThread is called)
  2. On end_turn (if user hasn't sent a message)

Let me now add the course correction logic to the thread-worker. I'll add it as an internal hook and modify the relevant parts:

Explored 2 files

Now I need to add course correction support. Rather than modifying InternalHooks (which is public-facing), I'll add the logic directly into the thread-worker. Let me add the course correction integration:

Explored 1 file

Let me look at the class properties and constructor:

Explored 1 file, 1 search

Now let me add the course correction operation tracking and the logic. First, let me add the import and the ops field, then modify the relevant parts:

Explored 1 file

Now let me add the import for course correction and modify the thread-worker:

Edited thread-worker.ts
+1

Now let me add the course correction ops field:

Edited thread-worker.ts
+2

Now let me add a setting flag to enable/disable course correction. Let me first check how configuration settings are accessed:

Explored 1 search

Let me look at how settings are typically defined:

Explored 2 files

Now let me add a setting for course correction:

Edited settings.ts
+1

Now let me create the course correction method in the thread-worker. Let me find a good place to add it:

Explored 1 file

Now let me add the course correction method. I'll add it after the runInferenceAndUpdateThread method and before setTestEphemeralError:

Explored 1 file
Edited thread-worker.ts
+61

Now I need to hook up the course correction to run at the right times:

  1. After tools complete (before running inference)
  2. On end_turn (if no queued messages)

Let me first update the tool:data handler to run course correction after tools complete:

Explored 1 file

I need to trigger the course correction before runInferenceAndUpdateThread. Let me update the logic:

Edited thread-worker.ts
+3

Now let me add the course correction check for the end_turn case. Let me look at that section again:

Explored 1 file
Edited thread-worker.ts
+4
Ran tool todo_write

Now let me run the typecheck to verify the changes:

$ pnpm exec tsc -b 2>&1 | head -100

Let me fix the errors. First let me find the correct function name for collecting guidance files:

Explored 1 file, 2 searches

I see - I need to use a different approach. Let me look at how to get guidance file content from the thread:

Explored 1 file

Let me look at how guidance files are extracted from threads more directly. Let me check how we can get the guidance file content directly from the user messages:

Explored 1 search

Let me look at the DiscoveredGuidanceFile type:

Explored 1 file, 1 search

I see - DiscoveredGuidanceFile only has URI and line count, not content. Let me update the course-correction.ts to use a simpler approach that extracts guidance content directly from the thread messages:

Created course-correction.ts
+253

Now let me add the missing documentation for the new setting:

Explored 3 files, 1 guidance file
Edited docs.ts
+6

Now let me run the typecheck again:

$ pnpm exec tsc -b 2>&1 | head -50

Let me fix this remaining error:

Explored 2 files, 1 search

I see - 'default' is not a valid AgentMode value. Let me fix this:

Edited course-correction.ts
+1
-3
$ pnpm exec tsc -b 2>&1 | head -50

Typecheck passes. Now let me run lint and format:

$ pnpm check:fix 2>&1 | head -100

All checks pass. Now let me run the tests to make sure nothing is broken:

Ran 2 commands

All tests pass. Let me update the todos:

Ran tool todo_write

I've implemented the course correction agent. Here's a summary of the changes:

Summary

New Files

  • core/src/threads/course-correction.ts - The course correction agent that:
    • Defines the course_correct tool with needsCorrection (boolean) and message (optional string) fields
    • Builds a system prompt instructing Gemini to detect when the main agent diverges from the plan
    • Uses runGeminiSync with GEMINI_3_PRO_PREVIEW model and forced tool calling
    • Extracts AGENTS.md content from the thread to include in the system prompt

Modified Files

  1. core/src/threads/thread.ts - Added course-correction as a new message source type
  2. core/src/threads/thread-worker.ts - Added:
    • Import for runCourseCorrection
    • courseCorrection AbortController in ops
    • runCourseCorrectionCheck() method that calls the course correction agent
    • Integration points after tool completion (before inference) and on end_turn
  3. core/src/configuration/settings.ts - Added experimental.courseCorrection.enabled setting
  4. cli/src/docs.ts - Documented the new setting

How It Works

  • Enabled via experimental.courseCorrection.enabled: true
  • Runs in parallel after tool execution completes (before next inference)
  • Runs on end_turn when no queued messages exist
  • If needsCorrection is true, injects a user message with source: { type: 'course-correction' } that steers the agent
  • The course correction message is visible in the thread and can be rendered differently in the UI
Handed off to T-4fd110d9-1d93-4131-be22-21246332c594