summaryrefslogtreecommitdiff
path: root/internal/executor/container.go
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-05-24 17:38:53 +0000
committerClaude <noreply@anthropic.com>2026-05-24 17:38:53 +0000
commit473d80224880dd718cb2612fd49b987cd6097b2c (patch)
tree3dcec19971c23ebbb35405fc87c0ea001fd1eb04 /internal/executor/container.go
parent952b7623ee9dceec15099043086622aa2aab4741 (diff)
feat(executor): MCP-oriented planning preamble, applied by ContainerRunner (Phase 2)
Rewrites the planning preamble to point the agent at the four MCP tools (ask_user/report_summary/spawn_subtask/record_progress) instead of the CLAUDOMATOR_QUESTION_FILE / CLAUDOMATOR_SUMMARY_FILE conventions: ask_user ends the turn, report_summary replaces the summary file, spawn_subtask replaces the POST-to-/api/tasks planning step. Git discipline is retained. ContainerRunner previously applied no preamble at all; it now prepends this preamble (via buildAgentInstructions) when the MCP back-channel is active and skip_planning is false, so the in-container agent is actually guided to use the tools. Gemini agents (no MCP) are unaffected. https://claude.ai/code/session_01SESwn7kQ7oP62trWw6pc39
Diffstat (limited to 'internal/executor/container.go')
-rw-r--r--internal/executor/container.go26
1 files changed, 20 insertions, 6 deletions
diff --git a/internal/executor/container.go b/internal/executor/container.go
index f0f728c..78c3ed7 100644
--- a/internal/executor/container.go
+++ b/internal/executor/container.go
@@ -305,12 +305,6 @@ func (r *ContainerRunner) runContainer(ctx context.Context, t *task.Task, e *sto
return fmt.Errorf("writing env file: %w", err)
}
- // Inject custom instructions via file to avoid CLI length limits
- instructionsFile := filepath.Join(workspace, ".claudomator-instructions.txt")
- if err := os.WriteFile(instructionsFile, []byte(t.Agent.Instructions), 0644); err != nil {
- return fmt.Errorf("writing instructions: %w", err)
- }
-
// Per-task MCP back-channel: mint a scoped token bound to this run's channel
// and write an mcp-config pointing the agent at the host agent MCP server.
mcpEnabled := false
@@ -327,6 +321,15 @@ func (r *ContainerRunner) runContainer(ctx context.Context, t *task.Task, e *sto
mcpEnabled = true
}
+ // Inject custom instructions via file to avoid CLI length limits. When the
+ // MCP back-channel is active, prepend the planning preamble that points the
+ // agent at the ask_user/report_summary/spawn_subtask/record_progress tools.
+ instructions := buildAgentInstructions(t, mcpEnabled)
+ instructionsFile := filepath.Join(workspace, ".claudomator-instructions.txt")
+ if err := os.WriteFile(instructionsFile, []byte(instructions), 0644); err != nil {
+ return fmt.Errorf("writing instructions: %w", err)
+ }
+
args := r.buildDockerArgs(workspace, agentHome, e.TaskID)
innerCmd := r.buildInnerCmd(t, e, isResume, mcpEnabled)
@@ -501,6 +504,17 @@ func (r *ContainerRunner) buildDockerArgs(workspace, claudeHome, taskID string)
// (the workspace is bind-mounted at /workspace).
const mcpConfigContainerPath = "/workspace/.claudomator-mcp.json"
+// buildAgentInstructions returns the agent's instructions, prepending the
+// MCP-tool planning preamble when the back-channel is active and planning is
+// not skipped.
+func buildAgentInstructions(t *task.Task, mcpEnabled bool) string {
+ instructions := t.Agent.Instructions
+ if mcpEnabled && !t.Agent.SkipPlanning {
+ instructions = withPlanningPreamble(instructions)
+ }
+ return instructions
+}
+
// writeMCPConfig writes a claude CLI mcp-config that registers the per-task
// agent MCP server over HTTP with a bearer token.
func writeMCPConfig(workspace, mcpURL, token string) error {