MentionTextarea inserted raw agent names (e.g. @Sarah Chen) but the
backend regex captured only the first word (@Sarah), causing mention
resolution to fail silently. Moved canonicalMentionHandle to shared/
so the renderer can produce space-free handles that the backend resolves
correctly.
The GPT-account (Codex) path supports tool calls and worked before; my
forced tool_choice broke it and was the wrong fix. The real regression was
strict:null in the rebuild's tool definitions, which made the endpoint drop
the tool list so the model had nothing to call — a "Done" run that hired no
one. Forcing then turned that silent failure into a red one.
Restore the original "auto" loop (no forced tool_choice, no finish tool) and
keep only the one-line strict:null omission. Codex now receives valid tools
on the working "auto" choice, as in the version that worked.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Forcing only the opening turn let a weak model take one token action and
stop, so a kickoff hired one agent (or none) and went quiet. Now every turn
is forced (tool_choice required) and the agent ends only by calling the new
`finish` tool — so it must keep hiring, delegating, and messaging until the
work is actually done. Finishing with zero actions, or returning no tool
call at all, fails the run loudly instead of faking success.
Prompts tell each agent it must call a tool every turn and finish only when
done. Tests drive weak-model stubs that act then finish, proving a full team
forms rather than a single gesture.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The whole premise is cheap models + skills + a team — so the control plane,
not the model, must guarantee action. Every adapter hardcoded
tool_choice:"auto", letting a weak model answer the kickoff with prose and
"succeed" having hired no one, delegated nothing, and said nothing.
Now the agent loop compels a tool call on the opening turn (tool_choice
plumbed through every backend: OpenAI/Responses/Chat, Anthropic, Codex,
Copilot, Azure, Custom, Gemini ANY mode, Bedrock any). If the forced turn
still yields no tool call, the run fails loudly instead of recording a
deceptive success — surfacing the problem (let it crash) rather than a
silent dead company. After it has acted, the model chooses freely.
Tested: a stub that rambles on "auto" but acts when forced now posts a
kickoff message; a prose-only first turn fails the run.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Engine-side writes - hires, delegated tasks, chat messages, run state -
only reached the renderer after a run finished: the queue worker sent
one snapshot-changed at the end, and nothing fired at claim time, so
the window sat frozen for the minutes a CEO run takes unless the user
reloaded by hand. The execution service now takes a notifyDataChanged
callback, the agent loop fires it after every tool-bearing iteration,
and the worker announces the claim itself, so the UI follows the
company working in real time.
A reasoning-heavy model can burn the whole max_tokens budget on
thinking blocks; the parsed turn then has neither text nor tool calls
and the loop treated it as a successful completion, marking a run done
when nothing happened. Such a first turn now fails the run so the
failure is visible and the heartbeat retries; later empty-text turns
after real tool work still complete normally.
The new app reached a real LLM but never ran an agent: the kickoff task_run
sat queued forever and runTask was a single text completion with no tools.
This adds the missing runtime:
- provider-tool-turn: OpenAI Responses + Anthropic Messages tool-use turns
- agent-tools + deliverable-writer: hire_agent, create_task,
update_task_status, write_deliverable (workspace-scoped, traversal-safe)
- agent-run-loop: real tool-use loop, capped iterations
- task-queue-worker: claims queued runs in a transaction and executes them
task-execution now drives the loop; a background worker auto-runs the
bootstrap CEO run so it hires its team, delegates tasks, and writes the first
deliverable into the bound workspace. Autonomy is gated by AGENTCOMPANY_NEW_AUTORUN
(tests run with it off to stay hermetic).