Skip to content

Factory Droid (factoryai-droid) hooks fail with schema mismatch on PreToolUse and PostToolUse — severely impacts Mission workflow #917

@dobedobedu

Description

@dobedobedu

What happened?

Entire's factoryai-droid hooks for PreToolUse and PostToolUse fail with exit code 1 on every invocation. This produces noisy error output in the Droid CLI on every tool call while Entire receives no data.

PreToolUse error:

HOOKS  PreToolUse → Task
 └─ Script: entire hooks factoryai-droid pre-tool-use
 └─ Result : Exit code: 1
   stderr:
   failed to capture pre-task state: tool_use_id is required

PostToolUse error:

HOOKS  PostToolUse → Task
 └─ Script: entire hooks factoryai-droid post-tool-use
 └─ Result : Exit code: 1
   stderr:
   failed to parse hook event: failed to parse hook input: json: cannot unmarshal string into Go struct field postToolHookInputRaw.tool_response of type struct { AgentID string "json:\"agentId\"" }

Impact on Droid Missions

This is especially painful during Droid Missions — Factory's orchestrated multi-subagent workflow feature. Missions spawn multiple parallel Task (subagent) tool calls, and each one triggers the failing PreToolUse hook. With a mission running 5-10+ subagents, this means:

  • 10-20+ failing hook executions per mission cycle
  • Each failing hook adds latency to the already-parallelized workflow
  • The cumulative slowdown dramatically degrades the automated/agentic experience
  • The constant error output makes it hard to follow what the mission is actually doing

For context, a typical mission cycle looks like:

HOOKS  Stop
 └─ Script: entire hooks factoryai-droid stop
 └─ Result : Exit code: 0

HOOKS  PreToolUse → Task
 └─ Script: entire hooks factoryai-droid pre-tool-use
 └─ Result : Exit code: 1    ← FAILS

HOOKS  PreToolUse → Task
 └─ Script: entire hooks factoryai-droid pre-tool-use
 └─ Result : Exit code: 1    ← FAILS

HOOKS  PreToolUse → Task
 └─ Script: entire hooks factoryai-droid pre-tool-use
 └─ Result : Exit code: 1    ← FAILS
... (repeats for every subagent)

Root cause

Two schema mismatches between what Entire expects and what Factory Droid provides in hook input JSON:

  1. Missing tool_use_id: Entire's pre-tool-use handler requires a tool_use_id field, but Droid's PreToolUse hook input does not include it. This is the same issue documented for Claude Code at PostToolUse hook not sending tool_use_id field as documented anthropics/claude-code#13241tool_use_id was never reliably sent by the agent platform.

  2. tool_response type mismatch: Entire expects tool_response to be a structured object with an agentId field (struct { AgentID string }), but Droid sends tool_response as a plain string (the raw tool output text). This causes the Go JSON unmarshal error.

Droid's actual hook input format (v0.98.0)

Per Factory docs (https://docs.factory.ai/reference/hooks-reference), Droid sends:

PreToolUse:

{
  "session_id": "...",
  "transcript_path": "...",
  "cwd": "...",
  "permission_mode": "...",
  "hook_event_name": "PreToolUse",
  "tool_name": "Task",
  "tool_input": { ... }
}

No tool_use_id field.

PostToolUse:

{
  "session_id": "...",
  "transcript_path": "...",
  "cwd": "...",
  "permission_mode": "...",
  "hook_event_name": "PostToolUse",
  "tool_name": "Task",
  "tool_input": { ... },
  "tool_response": "<raw string output, not a structured object>"
}

tool_response is a string, not an object with agentId.

Steps to reproduce

  1. Install Entire CLI v0.5.3
  2. In a git repo, run entire enable --agent factoryai-droid
  3. Start Droid in that repo: droid
  4. Ask Droid to perform any tool call (e.g. read a file)
  5. Observe PreToolUse and PostToolUse hook errors in Droid output
  6. Run a Droid Mission (multi-subagent workflow) to see the amplified impact

Entire CLI version

0.5.3

OS and architecture

macOS ARM64 (darwin/arm64)

Agent

Factory Droid (factoryai-droid)

Suggested fix

  1. Make tool_use_id optional in the PreToolUse parser — generate a fallback ID or skip the field when absent
  2. Handle tool_response as either a string or a structured object (union type / json.RawMessage) rather than requiring the agentId struct
  3. Alternatively, correlate tool calls via tool_name + session_id + timestamp instead of requiring tool_use_id
  4. Consider graceful degradation: if a hook fails to parse, continue with partial data rather than exiting with code 1 on every invocation

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions