fix(runtime): stop gating pi tool calls; Co-Founder approvals live at API layer

The Co-Founder beforeToolCall hook (introduced in 77f81a7) gated every
non-readonly pi tool call as a `dangerous_command` approval. Because
agents call `POST /api/companies/:id/messages`, `/agents` (hire), and
every other company mutation via bash→node/curl, the first bash call in
every Co-Founder run got parked on a 30-minute approval timeout. Users
observed it as "agents never talk to each other" and "every bash command
waits for approval"; both symptoms are the same bug.

The business-level approval flow (`hire_agent`, `document_review`,
`plan_review`, etc. in execution-policy.ts) already gates the events
users actually care about, at the HTTP route layer where the event
originates (routes-agents.ts:368 for hiring, document routes for
deliverables). Stacking a pi-level hook on top was duplicate gating with
the wrong taxonomy.

Removed:
- src/main/agent-runtime/approval-hook.ts (entire file, 137 LOC)
- `beforeToolCall` conditional in worker-runner.ts and the
  corresponding RPC method in worker-types.ts and runtime-bridge.ts
- `approvalHook` field + `resolveApproval` callback + shutdown
  `cancelAll` in runtime-bridge.ts / service-graph-pi-runtime.ts /
  wire-api-server.ts

Unchanged:
- `dangerous_command` approval type itself (still used by automation
  workflows and routes-misc.ts)
- CEO mode (already never attached the hook)
- All business-level approval types and their wiring
This commit is contained in:
ZacharyZhang-NY committed 2026-04-17 19:11:04 -04:00
1 parent 4cfb926971
commit 02ba887610
7 files changed
+8 -200

No files matched your search

-6
View File
@@ -79,12 +79,6 @@ export function wireApiServer(deps: WireApiServerDeps): AgentApiServer {
const onApprovalResolved = (approvalId: string, companyId: string, decision: string) => {
const automation = deps.serviceGraph.getAutomationService();
if (!automation) throw new Error("Automation service is not initialized.");
// Release any worker waiting on this approval *before* the business
// follow-ups fire, so the pi Agent unblocks immediately once the human
// decides. Automation state changes and thread updates are allowed to
// take longer — they do not hold back the running agent.
const piRuntime = deps.serviceGraph.getPiRuntime();
if (piRuntime) piRuntime.runtimeBridge.approvalHook.resolveApproval(approvalId, decision);
automation.handleApprovalResolved(approvalId, companyId, decision);
deps.threadIntegration.onApprovalResolved(approvalId, companyId, decision);
};