← Getting Started · Back to README · API Reference →
AIF Handoff is a Turborepo monorepo with six packages. The system automates task management: a React Kanban UI lets users create tasks, the API and agent operate through a centralized data layer backed by SQLite, and runtime execution goes through @aif/runtime so orchestration is provider-neutral.
┌─────────────┐ HTTP/WS ┌─────────────┐
│ Web (UI) │ ◄──────────────► │ API Server │
│ React+Vite │ │ Hono │
└─────────────┘ └──────┬───────┘
│
┌───────────────┐ Runtime API ┌──────┴───────┐
│ Runtime/Provider│ ◄────────────► │ Agent │
│ adapters │ │ Coordinator │
└───────────────┘ └──────┬───────┘
│
┌──────┴───────┐
│ @aif/runtime │
│ (registry + │
│ workflow spec)│
└──────┬───────┘
│
┌──────┴───────┐
│ @aif/data │
│ (DB access) │
└──────┬───────┘
│ SQLite
┌──────┴───────┐
│ Database │
│ (drizzle-orm) │
└──────────────┘
| Package | Name | Purpose |
|---|---|---|
packages/shared |
@aif/shared |
Types, schema, state machine, constants, env, logger |
packages/runtime |
@aif/runtime |
Runtime/provider contracts, registry, adapters, module loader |
packages/data |
@aif/data |
Centralized DB access layer (all SQL/repository operations) |
packages/api |
@aif/api |
Hono REST + WebSocket server (port 3009) |
packages/web |
@aif/web |
React Kanban UI (port 5180) |
packages/agent |
@aif/agent |
Coordinator + runtime-driven subagent orchestration |
shared ← data
shared ← runtime
runtime ← api
runtime ← agent
shared ← web (browser export only)
data ← api
data ← agent
No cross-dependencies between api, web, and agent. Runtime integration is:
web↔apivia HTTP/WebSocketagent/api→@aif/runtimefor run/resume/session/model-discovery flowsapi/agent→ SQLite via@aif/dataagent→apivia HTTP for best-effort broadcast notifications- Lint guard enforces this boundary:
apiandagentcannot import DB helpers from@aif/sharedor SQL builders directly.
Runtime execution is centralized in packages/runtime:
registry.tsregisters built-in adapters and optional external modules (AIF_RUNTIME_MODULES).workflowSpec.tsdefines runtime-independent execution intent (planner,implementer,reviewer, one-shot API flows).resolution.tsmerges profile data + env secrets + model/runtime overrides with capability checks.
Effective task profile selection order is:
- Task override (
tasks.runtime_profile_id) - Project default (
projects.default_task_runtime_profile_id) - System default (optional runtime bootstrap configuration)
The same pattern applies to chat mode using default_chat_runtime_profile_id.
Runtime-limit state is normalized once in @aif/runtime and then persisted in SQLite so every process sees the same view:
- adapters translate provider-specific quota signals into a shared
runtimeLimitSnapshotcontract; runtime_profiles.runtime_limit_snapshot_jsonstores the latest authoritative profile-level state;tasks.runtime_limit_snapshot_jsonstores a task-level copy when work is blocked by quota pressure or hard exhaustion.- API runs a background Codex indexer that reconciles
~/.codex/sessionsinto SQLite read-model tables (codex_sessions,codex_limit_heads,codex_limit_history,codex_index_cursors) so hot endpoints (/chat/sessions,/runtime-profiles) use DB reads instead of request-path filesystem scans.
The source is explicit in the snapshot (provider_api, sdk_event, api_headers, turn_usage) so upper layers do not need adapter-specific branching.
The coordinator treats persisted profile state as authoritative:
- exact snapshots can proactively gate new work when the configured safety threshold has already been crossed;
- heuristic snapshots can proactively gate new work when the provider says the runtime is blocked;
- blocked tasks resume through the existing
blocked_external+retryAfterrelease path when the provider reset time arrives.
Short-lived in-memory caches exist only for dedupe/throttling repeated identical writes; they are not the source of truth.
The coordinator (packages/agent/src/coordinator.ts) uses a dual-trigger model: it polls via node-cron every 30 seconds as a fallback and also reacts to real-time events from the API WebSocket (task creation, moves, and explicit agent:wake signals). Duplicate wakes are debounced, and both trigger sources share a single-flight poll loop; a trigger received during an active cycle requests one coalesced follow-up cycle. If the WebSocket is unavailable, the coordinator falls back to polling-only mode.
The coordinator supports parallel task execution (experimental, per-project). It first selects up to COORDINATOR_MAX_CONCURRENT_PROJECTS (default 4) independent project lanes and runs those lanes concurrently, while COORDINATOR_MAX_CONCURRENT_TASKS (default 12) remains a global safety ceiling across all lanes. A FIFO permit governor distributes global capacity across runnable lanes and waits for released slots instead of dropping later selected lanes. Within one lane, pipeline stages still drain sequentially to preserve project-local ordering. When a project has "Parallel Execution" enabled in settings, up to COORDINATOR_MAX_CONCURRENT_TASKS_PER_PROJECT (default 3) tasks per stage run concurrently via Promise.allSettled; non-parallel projects always process 1 task at a time. Tasks are atomically claimed (lockedBy/lockedUntil columns) with lock duration tied to the stage timeout; heartbeats renew the lock periodically. Stale claims (expired TTL or dead heartbeat) are auto-released. On shutdown, active locks are released immediately.
It delegates workflow stages to .claude/agents/ definitions, but actual execution transport/model/session behavior is adapter-owned through @aif/runtime:
Backlog ──[start_ai]──► Planning ──► Plan Ready ──► Implementing ──► Review ──► Done ──► Verified
│ │ │ │ │
│ │ │ │ └─[request_changes]──► Implementing (rework)
│ │ │ └─[auto-mode review gate]──► request_changes ─► Implementing (rework)
│ │ │ │
│ └─[request_ │ └─────────────────────────────────►
│ replanning]──┘
│
plan-coordinator implement-coordinator review + security sidecars
Skills-mode tasks (`useSubagents=false`) can opt into two extra stages:
Planning ──[runPlanImprove]──► Improve ──► Plan Ready
Implementing ──[runPostVerify]──► Verify ──► Review
| Stage Transition | Agent | Description |
|---|---|---|
| Backlog → Planning → Plan Ready | plan-coordinator |
Iterative plan refinement via plan-polisher |
| Planning → Improve → Plan Ready | /aif-improve |
Optional skills-mode plan refinement. Enabled per task with runPlanImprove; ignored when useSubagents=true |
| Plan Ready → Implementing → Review | implement-coordinator |
Parallel execution with worktrees + quality sidecars |
| Implementing → Verify → Review / Done | /aif-verify |
Optional skills-mode implementation verification against the plan before review. Enabled per task with runPostVerify; ignored when useSubagents=true |
| Review → Done / Review → request_changes → Implementing / Review → Done + manual review required | review-sidecar + security-sidecar (+ auto review gate in coordinator) |
Code review and security audit in parallel; in auto mode, structured blocking findings drive automatic rework until success or explicit manual handoff |
The pipeline includes four reliability layers for long-running autonomous execution:
- First-activity watchdog (SDK only): After agent start, if no tool call or subagent spawn arrives within
AGENT_FIRST_ACTIVITY_TIMEOUT_MS(default 60s), the agent is killed and restarted (up to 2 retries). Detects hung agents within seconds instead of waiting for the stale timeout. Disabled for CLI/API transports which do not stream tool events. - Heartbeat liveness: Task rows are updated with
lastHeartbeatAtduring agent activity and stage transitions. - Stale-stage watchdog: On each poll cycle, tasks stuck in
planning/improve/implementing/review/verifybeyond timeout are auto-recovered toblocked_externalwith retry backoff. - Runtime-limit auto-pause: Exact/heuristic persisted runtime-limit snapshots can proactively move new work to
blocked_externalbefore a provider hard-fails, and structuredresetAt/retryAfterSecondsreplace random quota backoff when available. - Transition reset: valid transitions clear watchdog state (
blocked*,retryAfter,retryCount) and refresh heartbeat baseline.
For stale implementing, recovery resumes from plan_ready to force a clean implementation pass instead of continuing a potentially inconsistent in-flight run.
Before launching implement-coordinator, the implementer computes dependency layers from the active plan (.ai-factory/PLAN.md or .ai-factory/FIX_PLAN.md) and injects a precomputed execution summary into the prompt.
This makes parallelism explicit:
- layers with one ready task are sequential,
- layers with multiple ready tasks are parallel and must dispatch
implement-workersubagents.
All agents are defined as markdown files in .claude/agents/*.md and loaded by runtimes that support agent definitions (e.g. Claude adapter via settingSources: ["project"]). The agent package orchestrates when to invoke them; the markdown files define what they do. For runtimes without agent definition support, the prompt policy falls back to slash-command injection.
Defined in packages/shared/src/stateMachine.ts. Human actions available per status:
| Status | Human Actions |
|---|---|
backlog |
start_ai |
planning |
(none — agent working) |
improve |
(none — agent working) |
plan_ready |
start_implementation, request_replanning, fast_fix |
implementing |
(none — agent working) |
review |
(none — agent working) |
verify |
(none — agent working) |
blocked_external |
retry_from_blocked |
done |
approve_done, request_changes |
verified |
(terminal state) |
Tasks have an autoMode flag. When true, the agent automatically transitions through all stages. This includes an automatic post-review gate: reviewer output is stored in a structured format, parsed deterministically, and converted into blocking findings for the next cycle. When blockers remain, the coordinator applies a request_changes-style transition (done -> implementing) with an agent comment containing required fixes. When false, the user must manually trigger start_implementation from plan_ready.
Auto-review strategy is controlled globally by AGENT_AUTO_REVIEW_STRATEGY:
full_re_review(default): every review cycle can trigger another automatic rework if current blocking findings exist.closure_first: rework cycles verify previously-blocking findings first; onlystill_blockingprevious findings can trigger another automatic loop.- If
closure_firstresolves previous blockers but the reviewer finds new blockers, or if max review iterations are reached, the task moves todonewithmanualReviewRequired=trueand preservedautoReviewStatefor explicit human triage.
Tasks also have a skipReview flag (default false). When true, the coordinator bypasses the review stage entirely — after successful implementation the task moves directly to done, skipping the review-sidecar and security-sidecar runs. This is useful for small changes or tasks where code review is unnecessary.
Skills-mode tasks (useSubagents=false) also have two opt-in flags. runPlanImprove inserts /aif-improve after the initial plan and before plan_ready. This is plan refinement: it may replace the stored plan only when the improver returns a complete plan-shaped update. runPostVerify inserts /aif-verify after implementation and before review. This is an execution validation gate: it stores verification output, passes through to review/done on pass or warn, and moves to blocked_external for a blocking gate result. Both flags default to false and are ignored for subagent tasks.
Flag interaction table:
useSubagents |
skipReview |
runPlanImprove |
runPostVerify |
Effective pipeline after planning starts |
|---|---|---|---|---|
true |
false |
ignored | ignored | Planning → Plan Ready → Implementing → Review → Done |
true |
true |
ignored | ignored | Planning → Plan Ready → Implementing → Done |
false |
false |
false |
false |
Planning → Plan Ready → Implementing → Review → Done |
false |
true |
false |
false |
Planning → Plan Ready → Implementing → Done |
false |
false |
true |
false |
Planning → Improve → Plan Ready → Implementing → Review → Done |
false |
true |
true |
false |
Planning → Improve → Plan Ready → Implementing → Done |
false |
false |
false |
true |
Planning → Plan Ready → Implementing → Verify → Review → Done |
false |
true |
false |
true |
Planning → Plan Ready → Implementing → Verify → Done |
false |
false |
true |
true |
Planning → Improve → Plan Ready → Implementing → Verify → Review → Done |
false |
true |
true |
true |
Planning → Improve → Plan Ready → Implementing → Verify → Done |
verify remains a coordinator stage, not a human action. That keeps it covered by the same claim, timeout, watchdog, runtime-profile, and activity-log machinery as other autonomous work. The semantic contract is narrower than review: verify validates the implementation against the accepted plan, while review/security sidecars evaluate code quality and risk.
Tasks carry a separate QA workflow that runs the /aif-qa --all pipeline (change-summary → test-plan → test-cases). It is driven by the API service packages/api/src/services/qaRunner.ts (modeled on commitGeneration.ts — fire-and-forget, returns a structured { ok, error } result and never throws), which executes the prompt through runApiRuntimeOneShot and writes three markdown artifacts to <paths.qa>/<branch-slug>/ (change-summary.md, test-plan.md, test-cases.md). The artifacts are persisted onto the task (qaChangeSummary, qaTestPlan, qaTestCases) and surfaced in the QA tab of the task detail view.
The branch-slug is computed deterministically (<safe-slug>-<git-hash-object-prefix>) as a hard contract with .claude/skills/aif-qa/SKILL.md, so the runner reads from the same directory the skill writes to. QA runs in the task's worktree root (worktreePath) when present, otherwise the project root.
Two trigger paths exist:
- Manual —
POST /tasks/:id/run-qa(available in the UI once the task reachesdoneorverified). - Automatic — the
autoQaflag (defaultfalse). Whentrue, the QA pipeline starts afterapprove_done(done → verified).
Progress is reported via qaStatus (idle → running → done/error) and the task:qa_started / task:qa_done / task:qa_failed WebSocket events.
Concurrent starts are serialized by an atomic DB claim (tryStartQaRun — a conditional UPDATE to running), so a duplicate manual POST or a manual+auto race never spawns two runtime runs. Every failure path releases the claim with a terminal qaStatus: "error", and on API startup any task left in running (e.g. a crash or restart mid-run) is reset to error (resetStaleQaRuns) so a stuck claim can never block future QA starts.
Tasks have a paused flag (default false). When true, the coordinator skips the task in all selection queries:
findCoordinatorTaskCandidate— paused tasks are not picked up for any stage (planning, plan-checking, implementing, reviewing).listDueBlockedExternalTasks— paused blocked tasks are not auto-released when their retry window elapses.listStaleInProgressTasks— paused tasks are not treated as stale by the watchdog, so they won't be force-recovered toblocked_external.
Important: pausing a task does not abort an already running runtime session. If a query is in flight, it will finish. The pause takes effect on the next coordinator cycle — the task simply won't be picked up for the next stage transition.
The Pause/Resume button is shown in the TaskDetail Actions bar for active processing stages (planning, plan_ready, implementing, review, blocked_external). It is hidden for backlog, done, and verified where the agent pipeline is not running.
Tasks expose an optional scheduledAt column (ISO-8601 UTC, nullable). On every
poll cycle the coordinator calls processDueScheduledTasks() which:
- Lists backlog tasks with
scheduledAt <= now(paused tasks skipped). - Transitions each from
backlogtoplanningusing the same state patch as the humanstart_aievent, clearingscheduledAtin the same write. - Appends a
[scheduler]entry to the task activity log. - Broadcasts
task:scheduled_firedvia WebSocket.
Past timestamps are rejected at the API layer with 400; null clears a
previous schedule. Scheduled firing is one-shot — the task never re-fires
automatically after scheduledAt is cleared.
Projects expose an autoQueueMode flag (default false). When true,
processAutoQueueAdvance() runs every poll cycle and for each such project
fills the pipeline up to a pool depth:
Ordinary task creation is intentionally append-only within a project's backlog:
when POST /tasks (or any other default createTask() caller) omits an
explicit position, the data layer assigns max(position) + 100 inside that
project's backlog. Auto-queue then consumes the smallest backlog position,
which makes ordinary backlog creation FIFO instead of LIFO.
- Sequential project (
parallelEnabled = false): pool depth =1. The next backlog task fires intoplanningonly after the previous one reaches a terminal status (done/verified). "In-flight" is counted by pipeline status, not by lock — so transitions between stages do not open a window for early advance. - Parallel project (
parallelEnabled = true): pool depth =COORDINATOR_MAX_CONCURRENT_TASKS_PER_PROJECT. Auto-queue keeps that many tasks in flight, advancing as soon as room frees up. For projects withgit.create_branches=true, this parallel branch-isolated path is available only whenAIF_TASK_WORKTREES_ENABLED=true; otherwise the project remains serial and the API rejects parallel auto-queue for that combination. When enabled, full-mode planning creates a sibling git worktree, stores its absolute path intasks.worktree_path, and downstream stages run from that path. Legacy branch-bound tasks withoutworktreePathstill force serial execution until they leave the pipeline. WhenAIF_AGENT_AUTO_QUEUE_COMMIT_GATE_ENABLED=true, Git-backed auto-queue projects that do not provide isolated task worktrees are also forced to pool depth1, even whenparallelEnabled=true, because task-scoped commits cannot safely share one working directory. Non-auto-queue projects retain their existing concurrency behavior.
The advance step:
- Compute
limit = parallelEnabled ? COORDINATOR_MAX_CONCURRENT_TASKS_PER_PROJECT : 1, then collapse it to1when branch isolation would use the shared project root. - Read
active = countActivePipelineTasksForProject(project)— counts tasks inplanning,plan_ready,implementing,review, orblocked_external. Backlog (source) anddone/verified(terminal) do not count. - While
active < limit, pick the next backlog task by ascendingposition(skipping paused tasks and tasks with futurescheduledAt), fire it intoplanning, append an[auto-queue]activity-log entry, and broadcastproject:auto_queue_advancedwith the new task id. - The fill loop runs in a single tick so a parallel project can start its full pool without waiting for additional poll cycles.
When AIF_AGENT_AUTO_QUEUE_COMMIT_GATE_ENABLED=true, the coordinator runs a
synchronous commit gate in an auto-queued task's project root or isolated
worktree before publishing the task as done:
- The backlog claim atomically stores the task's starting Git
HEADand marks its commit statepending. - A dirty worktree invokes the existing
/aif-commitworkflow with push disabled. The coordinator then verifies that the worktree is clean,HEADchanged, the expected branch is still checked out, and exactly one commit was created by the commit run. - A clean worktree is recorded as
no_changes, unlessHEADalready differs from the stored baseline (for example, the implementer committed directly); in that case the current SHA is recorded ascommitted. - The verified SHA is stored in
tasks.commit_shabefore the status changes todone. A commit failure moves the task toblocked_external, so it still counts as in flight and the next backlog task cannot start. - After a restart, a clean
HEADthat differs from the stored baseline is reconciled without creating a duplicate commit. Terminal tasks with an unresolved commit state defensively pause project advancement.
The flag defaults to false. In that state, terminal transitions and project
concurrency follow the legacy path and no auto-queue commit state is prepared.
Task worktrees are retained after done / verified so operators can inspect
follow-up changes. Handoff records the path but does not automatically remove
the sibling worktree directory.
Auto-queue and scheduled execution compose in the same poll cycle:
processDueScheduledTasks() runs first and fires every eligible backlog task
whose scheduledAt is due, then processAutoQueueAdvance() runs and tops up
the remaining pool slots. With the completion-commit flag enabled, a due
auto-queue task remains scheduled/backlogged while its Git worktree is dirty,
preventing unrelated pre-existing changes from entering the task's commit.
Order matters because once the scheduler advances a task, it counts as
in-flight and reduces how many slots auto-queue still needs to fill. Both
passes use the same atomic claimBacklogTaskForAdvance write so a row is moved
out of backlog exactly once even when both passes target the same task in the
same cycle.
The system supports bulk task creation from a project's .ai-factory/ROADMAP.md file via POST /projects/:id/roadmap/import.
Flow:
- API reads
ROADMAP.mdfrom the project root - Agent SDK (haiku model) converts markdown milestones into structured JSON
- Response is validated via zod schema
- Tasks are created in batch with deduplication (by
projectId + normalizedTitle + roadmapAlias) - Each task receives automatic tags:
roadmap,rm:<alias>,phase:<N>,phase:<name>,seq:<NN> - WebSocket broadcasts
task:createdper task andagent:wakeafter batch
Deduplication: Re-running import with the same alias is safe — existing tasks with matching titles are skipped. This makes the endpoint idempotent for reruns.
Ordering semantics: Roadmap import is the explicit front-of-queue path.
Imported tasks receive explicit backlog positions ahead of the current backlog
minimum so phase/sequence order wins even though ordinary task creation now
appends to the backlog tail. This ordering is intentional and separate from the
default POST /tasks behavior.
Legacy data: Existing backlog rows are not rewritten automatically during
deploy because operators can manually reorder backlog positions. If legacy rows
still reflect old LIFO-era positions, use the opt-in normalization utility
documented in docs/configuration.md.
Tag taxonomy: Tags enable UI filtering. The roadmap quick filter in the Board shows only roadmap-generated tasks. When the roadmap filter is active, a sub-filter row displays all available roadmapAlias values (e.g., v1.0, v2.0) as clickable chips, allowing users to narrow results to a specific roadmap. Selecting no alias shows all roadmap tasks; selecting one or more aliases filters to only those. Tags like phase:backend allow additional grouping refinements.
Logging: Import logs at INFO level for start/finish with counts, DEBUG for per-task decisions, and ERROR for parse/validation failures. Check API logs during failures by filtering for the roadmap-generation component.
The API broadcasts events via WebSocket (/ws endpoint) on every state change:
| Event | Trigger |
|---|---|
task:created |
New task created |
task:updated |
Task fields updated |
task:moved |
Task status changed via state machine |
task:deleted |
Task deleted |
task:qa_started |
QA pipeline started (manual run-qa or auto-trigger) |
task:qa_done |
QA pipeline finished successfully |
task:qa_failed |
QA pipeline failed |
agent:wake |
Coordinator should check for work |
project:runtime_limit_updated |
Runtime-profile limit snapshot persisted or cleared |
The web UI connects via useWebSocket hook and invalidates React Query caches on incoming events. The agent coordinator also subscribes to this WebSocket to receive wake signals for immediate task processing (see Agent Pipeline above).
Agent tool events are tracked in each task's agentActivityLog field. Two modes are supported (configured via ACTIVITY_LOG_MODE):
- sync (default): Each event writes immediately to the database.
- batch: Events are buffered in an in-memory queue per task and flushed when the batch size, max age timer, or stage boundary is reached. Shutdown handlers ensure buffered entries are persisted on
SIGINT/SIGTERM.
The API separates task list reads from task detail reads to keep project board loads bounded:
GET /tasks?projectId=<uuid>requires a project id and returns lightweightTaskListItemrows fromlistTaskListItems(projectId).TaskListItemincludes board, list, filtering, command-palette, runtime-limit, and metric fields plus the derivedhasPlanflag.TaskListItemintentionally excludes heavy detail-only fields: attachments, plan text, implementation log, review comments, agent activity log, runtime options, auto-review state, and QA markdown artifacts.GET /tasks/:idremains the full task detail endpoint for task detail, chat, comments, and agent workflows.GET /projects/overviewuseslistProjectTaskOverviews()to serve compact per-project counts, metric totals, and small title previews without loading every task row into the web client.
SQLite via better-sqlite3 with drizzle-orm for type-safe queries. Schema is defined in packages/shared/src/schema.ts, and all DB reads/writes are executed through packages/data/src/index.ts.
Key tables:
- tasks — task data, status, plan/logs, heartbeat metadata, runtime override fields (
runtime_profile_id,model_override,runtime_options_json), runtime session id (session_id), internal stage-scoped runtime retry pin (active_runtime_status,active_runtime_selection_json), auto-review convergence state (manual_review_required,auto_review_state_json), and task-level runtime-limit copy (runtime_limit_snapshot_json,runtime_limit_updated_at). The active runtime fields are distinct fromsession_idandruntime_limit_snapshot_json; they store the runtime/profile/model/options selected for same-status retries and are cleared on stage or human transitions exceptretry_from_blocked. - runtime_profiles — project-scoped or global runtime/provider profiles with non-secret transport/model config plus authoritative runtime-limit state (
runtime_limit_snapshot_json,runtime_limit_updated_at) - projects — project metadata plus default runtime profile ids for tasks and chat
- chat_sessions / chat_messages — persisted chat state with runtime profile/session linkage
- codex_sessions — indexed Codex session metadata keyed by runtime session id and source file state
- codex_limit_heads / codex_limit_history — latest and recent normalized Codex limit snapshots keyed by account fingerprint/project scope/limit id
- codex_index_cursors — per-indexer progress/watermark state for incremental reconcile
- task_comments — human/agent comments with optional attachments
Runtime index bootstrap creates the following indexes via CREATE INDEX IF NOT EXISTS at startup:
idx_tasks_status— coordinator stage filteringidx_tasks_retry_after— blocked-task retry scansidx_tasks_project_id— project-scoped task listsidx_tasks_status_retry— composite for coordinator retry queriesidx_tasks_project_status— composite for ordered task-list queriesidx_task_comments_task_id— comment lookups by taskidx_tasks_locked— parallel execution: find unlocked or stale-locked tasksidx_codex_sessions_project_root_updated/idx_codex_sessions_file_path— local Codex session listing and session-id/file-path lookupidx_codex_limit_heads_lookup— account/project/limit scoped head overlay queriesidx_codex_limit_history_head/idx_codex_limit_history_account— bounded recent limit history by head and account scope
- Getting Started — installation and setup
- API Reference — REST endpoints and WebSocket protocol