Align team-building SOP to tool-based flow; deprecate HTTP hire path (C4 part 5/5)

Rewrite `ceo-modes/team-building.en.md` to describe the `hire_agent`
and `file_approval` pi tools introduced in C4 parts 1-3, replacing the
pre-C4 Node.js `fetch` snippets that showed the CEO how to POST to
`/api/companies/:id/agents` and `/api/companies/:id/approvals`.

The SOP now:
- Lists `hire_agent` args as a table (name / role / connectorId /
  model + optionals) instead of a JSON body with hard-coded headers.
- Lists `file_approval` args the same way, pointing at
  `approve_ceo_strategy` as the canonical use case.
- Preserves the `STRATEGY_BEFORE_HIRES` / `STRATEGY_ALREADY_FILED`
  ordering gate, surfaced through the tool-layer error codes
  (`file_approval.strategy.before_hires` / `.already_filed`).
- Keeps the goal-creation fetch snippet because goal creation is not
  yet exposed as an internal tool; flagged with a "use `bash` for now"
  hint so the CEO does not conflate the two patterns.

HTTP deprecation:
- `POST /api/companies/:id/agents` carries `@deprecated since C4`
  JSDoc and emits `log.warn('[deprecated][C4] ...')` on every
  successful call so residual legacy callers (UI forms, automation
  tests, unmigrated scripts) are auditable in logs.
- `POST /api/companies/:id/approvals` with `type=approve_ceo_strategy`
  emits the same warn; other approval types still use the HTTP route
  and are not flagged (they have no tool equivalent yet).

Neither route is removed — existing clients keep working. Removal is
gated on tool-path eval coverage landing in a follow-up.

tests: pnpm typecheck + pnpm test:unit (529) + pnpm test:eval (8/8) green
This commit is contained in:
ZacharyZhang-NY committed 2026-04-20 14:29:05 -04:00
1 parent 003490e16b
commit 03864f3bd8
3 files changed
+55 -48

No files matched your search

+13
View File
@@ -95,6 +95,16 @@ export function registerAgentRoutes(server: AgentApiServer) {
server.json(res, 200, agents);
});
/**
* @deprecated since C4 (2026-04-20). Agents should file hires via the
* first-class `hire_agent` pi tool (see
* `src/main/worker/runtime/internal-tools/hire-agent-tool.ts`). This
* HTTP route stays live for legacy clients (UI form post, automation
* tests, unmigrated scripts) during the deprecation window and will
* be removed once tool-path eval confirms no regressions. Every
* successful request emits a `log.warn` tagged with `[deprecated]`
* so residual callers are easy to audit.
*/
server.addRoute("POST", "/api/companies/:companyId/agents", (_req, res, params, token, body) => {
const companyId = requireParam(params, "companyId");
if (companyId !== token.companyId) {
@@ -105,6 +115,9 @@ export function registerAgentRoutes(server: AgentApiServer) {
server.json(res, 403, { error: "Current agent is not allowed to request hires" });
return;
}
log.warn(
`[deprecated][C4] POST /api/companies/${companyId}/agents — prefer the hire_agent internal tool (caller agent=${token.agentId}).`,
);
const reportsToProvided =
typeof body === "object" &&
body !== null &&
+14
View File
@@ -17,6 +17,15 @@ export function registerApprovalRoutes(server: AgentApiServer) {
const onDomainChanged = server.onDomainChanged;
const onWakeAgent = server.onWakeAgent;
/**
* @deprecated since C4 (2026-04-20) for the `approve_ceo_strategy`
* flow. CEOs should file that approval via the `file_approval` pi
* tool (see `src/main/worker/runtime/internal-tools/file-approval-
* tool.ts`). Other approval types still use this HTTP route. Once
* every approval type has a tool surface, this route is removed
* outright; until then, the deprecated warn is scoped to
* `approve_ceo_strategy` so signal stays clean.
*/
server.addRoute("POST", "/api/companies/:companyId/approvals", (_req, res, params, token, body) => {
const companyId = requireParam(params, "companyId");
if (companyId !== token.companyId) {
@@ -33,6 +42,11 @@ export function registerApprovalRoutes(server: AgentApiServer) {
return;
}
const input = parsed.data;
if (input.type === "approve_ceo_strategy") {
log.warn(
`[deprecated][C4] POST /api/companies/${companyId}/approvals type=approve_ceo_strategy — prefer the file_approval internal tool (caller agent=${token.agentId}).`,
);
}
if (server.companyRefError(res, companyId, [
{ id: input.relatedTaskId, table: "tasks", label: "related task" },
{ id: token.agentId, table: "agents", label: "requesting agent" },