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).