Repository navigation
0.21.0
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_keyis the exclusive slot a run holds:''for an exclusive agent (one per organisation),enqueueRun({ concurrencyKey })for one active run per key, NULL forexclusive: false(no slot, neverdeduplicated). The unique index is(tenant_id, agent_key, concurrency_key)over active rows with a key;findActiveRuntakes the key (default'').triage-researchis nowexclusive: false. From PR #77.- The plugin
AgentCtx(@/plugins/api) gainsinterrupt(ask)andchatModel { provider, model };AgentInterruptAsk/AgentInterruptAnswerare exported.PROMPT_REGISTRYis typed so a plugin's prompt key indexes it.agent-runs,ai-promptsandagent-modelstests compare only the kit's own agents and prompts. - Replay (D38):
replay.ts(replayRun,listReplayableRuns,diffJson,ReplayMissError),scripts/agent-replay.ts+ theagent:replayscript (--candidate,--live),ctx.once(key, fn, { replay: 'rerun' | 'inner' }),decideWithShapes/toDecisionexported fromdecisions.ts, the skillrf-agent-replay, andPROCESS_TEST_TIMEOUTon theconfig/kit-onlyvitest projects. enqueueRun(db, cfg, env, input)takes the config and enforcesAGENT_MAX_ACTIVE_RUNS_PER_TENANT(default 50, 429agent_runs_limit) andAGENT_TENANT_DAILY_COST_USD(429ai_budget_exceeded).POST /api/agents/runs/batch(enqueueRunBatch,createAgentRunBatch{Request,Response}Schema,AGENT_RUN_BATCH_MAX= 100): one non-exclusive agent (400agent_exclusiveotherwise), per-input errors, onecreateBatch()with a per-instance fallback;GET /api/agents/runs?batchId=.ctx.scope(prefix)andctx.map(key, items, fn, { concurrency, keyOf })(services/agents/fanout.ts).- The ledger is one
ai_usagerow PER CALL carryingagent_run_id, written as each call returns by the run's meter (services/agents/budget.ts) for every call throughctx.chat.clientandctx.decide, so a run cancelled mid-loop keeps every turn it paid for (issue #2, from PR #74). The example agents no longer callrecordUsage;ctx.recordUsage(call)is for a client an agent builds itself;GET /api/agents/runs/:idreturnsusage. - Budgets:
meta.budget { maxTokens, maxCostUsd }overAGENT_RUN_MAX_TOKENS/AGENT_RUN_MAX_COST_USD, checked before each metered call across attempts; over →failed, event codeagent_budget_exceeded, not retried. - Policies (issue #1, from PR #73):
meta.policy { maxTurns, maxToolCalls, maxDurationSeconds, repeatedFailureLimit, onExhaustion }, passed torunToolLoopaspolicy, counted across attempts (ToolLoopCheckpoint.activeMscarries active time).'final-answer'(default) forces one call to the terminal tool (salvaged: true);'fail'throwsToolLoopExhaustedError→failed, event codeagent_policy_exhausted. No policy, no change.research-topic's hand-written salvage is now its policy;GET /api/agentsitems carrypolicy, shown on the Agents page. runToolLoop'sauthorizeTool(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