Skip to content

Issue 4: Orchestrator MCP tools (in wizard-tools) #623

@gewenyu99

Description

@gewenyu99

Issue 4: Orchestrator MCP tools (in wizard-tools)

Epic: Task-queue orchestrator runner · Depends on: #622 (QueueStore) · PR: #608

Why

Agents need structured tools to seed and grow the queue, signal completion with a
handoff, and read prior handoffs. The loop guards keep dynamic enqueue from
running away.

The orchestrator tools live in the existing wizard-tools in-process MCP server,
alongside the env tools and the audit tools (audit_seed_checks,
audit_add_checks, audit_resolve_checks, wizard-tools.ts:795–953). Per-task
availability is controlled by disallowedTools and canUseTool. The tool
definitions sit in their own file and register into the one server.

Scope / deliverable

  1. Add the orchestrator tools to the wizard-tools server. Put the definitions
    in queue-tools.ts as a buildOrchestratorTools(queueStore) factory, following
    the tool(name, desc, zodSchema, handler) pattern (wizard-tools.ts:531), and
    register them in createWizardToolsServer when a QueueStore is passed
    (threaded through initializeAgent options the way askBridge is). The linear
    arm passes no QueueStore, so the tools stay off there.
  2. Tools. All mutate the in-memory QueueStore under its mutex; the disk
    reflection flushes async per Issue 3: Queue + persistence layer #622.
    • enqueue_task { type, inputs, dependsOn?, model?, reason }, for seeding and
      for dynamic enqueue. It validates type against the set of valid task types
      injected at build time (the registry is Issue 6: Agent-prompt and mini-skill format + seed prompt #625; a stub set lets Issue 4: Orchestrator MCP tools (in wizard-tools) #623 stand alone),
      rejects unknown deps, stamps depth = parentDepth + 1, enforces the guards,
      and returns the new id.
    • complete_task { taskId, status: 'done'|'failed', handoff }, the completion
      signal. handoff is a structured object validated by this tool's zod schema:
      goals (what the task was asked to achieve), did (what it did),
      forNextAgent (what the next agent should know), filesTouched?. It patches
      the in-memory task status and writes handoffs/<id>.json. The schema forces
      the agent to fill each field, so the handoff is always well-formed.
    • read_handoffs { type? | taskId? }, to read prior structured handoffs, a
      dependency's output or all upstream handoffs. Downstream tasks also get their
      dependencies' handoffs appended to their prompt automatically ( Issue 6: Agent-prompt and mini-skill format + seed prompt #625), so this
      is for opportunistic lookups.
  3. Termination and loop guards in enqueue_task. Each returns an actionable
    isError result and emits an orchestrator guard tripped event:
    • a global task budget (for example 25 tasks per run)
    • a depth cap (reject when parent.depth >= MAX_DEPTH, for example 4)
    • {type, inputs} dedup (reject a re-enqueue of existing non-failed work)
    • a per-type cap (for example 2 instrument-events)
    • the executor-loop iteration cap and the per-agent tool-call force-exit live in
      Issue 5: Executor framework + fresh per-task agent #624
  4. Add the new tool names to WIZARD_TOOL_NAMES (wizard-tools.ts:1129),
    fully qualified as mcp__wizard-tools__* (the colon form at :1126 is a known
    landmine). Leaf task types add enqueue_task to disallowedTools so
    canUseTool (agent-interface.ts:499) denies it at the tool layer.

Key files

  • new src/lib/programs/orchestrator/queue-tools.ts (buildOrchestratorTools())
  • src/lib/wizard-tools.ts (register when a QueueStore is present, extend
    WIZARD_TOOL_NAMES)
  • src/lib/programs/orchestrator/queue.ts (from Issue 3: Queue + persistence layer #622)

Acceptance criteria

  • The tools register in the wizard-tools server when a QueueStore is
    passed, and stay off on the linear arm.
  • All tools mutate the in-memory QueueStore. complete_task writes a
    structured handoffs/<id>.json and flips status.
  • enqueue_task rejects an unknown type or unknown dependsOn with an
    isError result.
  • Each guard (budget, depth, dedup, per-type) trips with an actionable message
    and emits orchestrator guard tripped { guard, type }.
  • Registered tool names are mcp__wizard-tools__*, and a leaf type with
    enqueue_task disallowed is denied by canUseTool.
  • Unit tests cover the happy path and each guard.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions