Skip to content

0.21.0

Choose a tag to compare

@cliftonc cliftonc released this 16 Oct 20:23
· 40 commits to main since this release
0.21.0
7f31c0f

Agents can run many at once, in batches and fan-outs, with a usage row per call, budgets and tool-loop policies; plugin agents can ask questions; and pnpm web agent:replay re-runs past runs with today's code.

  • agent_runs.concurrency_key is the exclusive slot a run holds: '' for an exclusive agent (one per organisation), enqueueRun({ concurrencyKey }) for one active run per key, NULL for exclusive: false (no slot, never deduplicated). The unique index is (tenant_id, agent_key, concurrency_key) over active rows with a key; findActiveRun takes the key (default ''). triage-research is now exclusive: false. From PR #77.
  • The plugin AgentCtx (@/plugins/api) gains interrupt(ask) and chatModel { provider, model }; AgentInterruptAsk / AgentInterruptAnswer are exported. PROMPT_REGISTRY is typed so a plugin's prompt key indexes it. agent-runs, ai-prompts and agent-models tests compare only the kit's own agents and prompts.
  • Replay (D38): replay.ts (replayRun, listReplayableRuns, diffJson, ReplayMissError), scripts/agent-replay.ts + the agent:replay script (--candidate, --live), ctx.once(key, fn, { replay: 'rerun' | 'inner' }), decideWithShapes / toDecision exported from decisions.ts, the skill rf-agent-replay, and PROCESS_TEST_TIMEOUT on the config / kit-only vitest projects.
  • enqueueRun(db, cfg, env, input) takes the config and enforces AGENT_MAX_ACTIVE_RUNS_PER_TENANT (default 50, 429 agent_runs_limit) and AGENT_TENANT_DAILY_COST_USD (429 ai_budget_exceeded).
  • POST /api/agents/runs/batch (enqueueRunBatch, createAgentRunBatch{Request,Response}Schema, AGENT_RUN_BATCH_MAX = 100): one non-exclusive agent (400 agent_exclusive otherwise), per-input errors, one createBatch() with a per-instance fallback; GET /api/agents/runs?batchId=.
  • ctx.scope(prefix) and ctx.map(key, items, fn, { concurrency, keyOf }) (services/agents/fanout.ts).
  • The ledger is one ai_usage row PER CALL carrying agent_run_id, written as each call returns by the run's meter (services/agents/budget.ts) for every call through ctx.chat.client and ctx.decide, so a run cancelled mid-loop keeps every turn it paid for (issue #2, from PR #74). The example agents no longer call recordUsage; ctx.recordUsage(call) is for a client an agent builds itself; GET /api/agents/runs/:id returns usage.
  • Budgets: meta.budget { maxTokens, maxCostUsd } over AGENT_RUN_MAX_TOKENS / AGENT_RUN_MAX_COST_USD, checked before each metered call across attempts; over → failed, event code agent_budget_exceeded, not retried.
  • Policies (issue #1, from PR #73): meta.policy { maxTurns, maxToolCalls, maxDurationSeconds, repeatedFailureLimit, onExhaustion }, passed to runToolLoop as policy, counted across attempts (ToolLoopCheckpoint.activeMs carries active time). 'final-answer' (default) forces one call to the terminal tool (salvaged: true); 'fail' throws ToolLoopExhaustedError → failed, event code agent_policy_exhausted. No policy, no change. research-topic's hand-written salvage is now its policy; GET /api/agents items carry policy, shown on the Agents page.
  • runToolLoop's authorizeTool(call) refuses a tool call by rule before it is gated or run (issue #3, from PR #75).
  • CLI: rocketflare agents list, agents run <key> --input x.json | --batch x.jsonl, agents runs list [--batch id]. Rationale and known gaps: docs/CONCEPTS.md §9 "Agents", "Replay (D38)", "Volume (D39)" and "Policy (D39)".

Thanks to @benfrostmosaic (#77, the concurrency slots this is built on) and @NANDANS26 (#73, #74, #75, rolled into #78).

Breaking: enqueueRun now takes cfg (enqueueRun(db, cfg, env, …)), and an agent run's usage is several ai_usage rows (one per call, grouped by agent_run_id) rather than one summed row — delete any recordUsage / onUsage ledger write in your own agents, or it double-counts. See the porting note.

Porting note: docs/upgrades/0.21.0.md — pnpm kit:upgrade or /rf-upgrade in a copy.

Full changelog: 0.20.0...0.21.0