Base URL http://localhost:3333/api/ · Authentication · Conventions

Closed Loop System (PRD-091)

AGNT runs a self-improvement loop across four primitives that together let goals fire on a cadence, mutations prove themselves before promoting, safe insights auto-apply, contracts enforce runtime invariants, and regressions auto-revert. This section is required reading for any agent that touches scheduling, auto-apply, budgets, or revert.

The four primitives

Primitive Base path What it stores Layer
Schedules /api/schedules Durable cron entries (target + cron + next_run). Survives backend restart. 1 (Clock)
Wallets /api/wallets Linear capability budgets (root + sub-wallets). Sub-wallets can never exceed parent balance. 3 (Budgets)
Contracts /api/contracts Runtime invariants mined from successful executions ("output must be JSON", "step count ≤ 5"). 5 (Invariants)
Mutation History /api/mutations Every router-applied change, with before-snapshot + fitness baseline. 7 (Provenance)

Plus the Autonomy Router at POST /api/insights/route which decides per pending insight whether to direct-apply, gate via sandbox, escalate to the user, or skip. Driven by EvolutionSettingsModel.autonomy (off by default).

When to use which endpoint (intent → call)

User says... Call
"Run this goal every morning at 9 ET" POST /api/schedules with targetType:'goal', cron:'0 9 * * *', timezone:'America/New_York'
"When will my schedule fire next?" POST /api/schedules/preview (no persist) — or GET /api/schedules/:id and read next_run
"Show me what AGNT auto-changed lately" GET /api/mutations
"Did that auto-change regress quality?" POST /api/mutations/:id/canary-check
"Undo that auto-applied change" POST /api/mutations/:id/revert
"Turn on autonomy" POST /api/insights/settings with { autonomy: { enabled: true } }
"Apply all my safe pending insights" POST /api/insights/route (sweeps every pending insight through the router)
"Route just this one insight" POST /api/insights/:id/route
"What's my budget?" GET /api/wallets/root
"Add credit to my budget" POST /api/wallets/root/topup
"Spin up a sub-budget for this agent" (server-side) WalletService.allocate(...) — no public route yet
"Show this agent's spend ledger" GET /api/wallets/:id/ledger
"Does this output satisfy our quality contracts?" POST /api/contracts/check
"Show me what rules have been mined" GET /api/contracts

Safety contract (the agent MUST respect this)

  1. Never flip autonomy.enabled on the user's behalf without explicit, in-conversation confirmation. It is off by default for a reason.
  2. Never call POST /api/insights/:id/apply on insights with priority: 'critical' or category: 'parameter_tune' | 'bottleneck' without explicit confirmation.
  3. Always call POST /api/mutations/:id/canary-check before suggesting revert. Show the user the verdict (regression: true|false, delta, fitnessAfter).
  4. Always call GET /api/wallets/root before scheduling a recurring goal that will incur LLM cost — confirm there is budget.
  5. Default to escalation, not direct-apply. When in doubt, use POST /api/insights/route (which respects the router) rather than POST /api/insights/:id/apply (which bypasses it).

Layered guarantees the safety contract relies on

  • The router itself returns { decision: 'escalate', reason: 'autonomy_disabled' } for every insight when autonomy.enabled === false. Flipping enabled is the only way auto-apply turns on.
  • Every router-applied mutation captures fitness_before at apply time. Revert is non-lossy because the before-snapshot lives in mutation_history.
  • VerifierGate enforces delta > MIN_DELTA (0.05) AND structural-constraint gates before promote. A regression cannot pass the gate.
  • Wallets cap blast radius — even if autonomy is on AND all gates pass, a tool with a depleted wallet cannot keep spending.

Default policy values (live in AutonomyPolicy.DEFAULTS)

{
  "enabled": false,
  "minConfidence": 0.7,
  "minDelta": 0.05,
  "maxBlastRadius": 0.5,
  "dailyBudget": 20,
  "allowedCategories": [
    "memory", "prompt_refinement", "tool_preference",
    "contract_proposal", "skill_recommendation", "pattern", "antipattern"
  ],
  "requireGateAbove": 0.45
}

Insight with blast_radius >= requireGateAbove is routed gated (sandbox-tested) instead of direct. Insight with blast_radius > maxBlastRadius is escalated (human required).

Realtime events the frontend listens for

Event When it fires
autonomy.router.decision Router emits a decision per insight
autonomy.mutation.applied A mutation lands in mutation_history
autonomy.canary.regression Periodic canary sweep detects a regression
scheduler.tick Scheduler tick fires a schedule
scheduler.run.complete A scheduled run finishes

(Implemented in frontend/src/composables/useRealtimeSync.js.)


Goal Routes

Base path: /api/goals

Health Check

GET /health

  • Authentication: None
  • Description: Check if the goal service is running
  • Response:
{
  "status": "OK"
}

Get All Goals

GET /

  • Authentication: Required
  • Description: Retrieve all goals for the authenticated user. Includes aggregated token usage from goal evaluations.
  • Response:
[
  {
    "id": "goal-id",
    "title": "Goal Title",
    "description": "Goal description",
    "status": "active|paused|completed|validated|needs_review|failed",
    "priority": "low|medium|high",
    "task_count": 5,
    "completed_tasks": 3,
    "input_tokens": 15000,
    "output_tokens": 3200,
    "total_tokens": 18200,
    "estimated_cost": 0.045,
    "createdAt": "2024-01-01T00:00:00Z",
    "updatedAt": "2024-01-01T00:00:00Z"
  }
]

Create Goal

POST /create

  • Authentication: Required
  • Body:
{
  "title": "Goal Title",
  "description": "Goal description",
  "priority": "low|medium|high",
  "config": {}
}
  • Response:
{
  "success": true,
  "goal": {
    "id": "goal-id",
    "title": "Goal Title",
    "description": "Goal description",
    "status": "active",
    "priority": "medium",
    "config": {},
    "createdAt": "2024-01-01T00:00:00Z",
    "updatedAt": "2024-01-01T00:00:00Z"
  }
}

Execute Goal

POST /:goalId/execute

  • Authentication: Required
  • Parameters:
    • goalId (path): Goal ID
  • Body (optional):
{
  "provider": "anthropic",
  "model": "claude-sonnet-4-20250514"
}
  • Description: Start goal execution. Any failed or stuck tasks are reset to pending. The provider/model override the user's default settings for this execution and all downstream operations (task execution, evaluation, insight extraction, skill evolution).
  • Response:
{
  "message": "Goal execution started",
  "goalId": "goal-id",
  "status": "executing"
}

Get Goal by ID

GET /:id

  • Authentication: Required
  • Parameters:
    • id (path): Goal ID
  • Description: Retrieve a specific goal with tasks and aggregated token usage from evaluations and task executions
  • Response:
{
  "goal": {
    "id": "goal-id",
    "title": "Goal Title",
    "description": "Goal description",
    "status": "active|paused|completed|validated|needs_review|failed",
    "priority": "low|medium|high",
    "config": {},
    "tasks": [],
    "total_duration": 120,
    "credits_used": 120,
    "input_tokens": 15000,
    "output_tokens": 3200,
    "total_tokens": 18200,
    "estimated_cost": 0.045,
    "createdAt": "2024-01-01T00:00:00Z",
    "updatedAt": "2024-01-01T00:00:00Z"
  }
}

Get Goal Status

GET /:id/status

  • Authentication: Required
  • Parameters:
    • id (path): Goal ID
  • Description: Get the current status of a goal
  • Response:
{
  "goalId": "goal-id",
  "status": "active|paused|completed|failed",
  "progress": 75,
  "lastExecution": "2024-01-01T00:00:00Z",
  "nextExecution": "2024-01-01T01:00:00Z"
}

Pause Goal

POST /:id/pause

  • Authentication: Required
  • Parameters:
    • id (path): Goal ID
  • Description: Pause an active goal
  • Response:
{
  "success": true,
  "message": "Goal paused successfully"
}

Resume Goal

POST /:id/resume

  • Authentication: Required
  • Parameters:
    • id (path): Goal ID
  • Body (optional):
{
  "provider": "anthropic",
  "model": "claude-sonnet-4-20250514"
}
  • Description: Resume a paused or failed goal. Failed/stuck tasks are reset to pending. Provider/model are forwarded to all downstream operations.
  • Response:
{
  "message": "Goal resumed"
}

Delete Goal

DELETE /:id

  • Authentication: Required
  • Parameters:
    • id (path): Goal ID
  • Description: Delete a goal by ID
  • Response:
{
  "success": true,
  "message": "Goal deleted successfully"
}

Execute Goal Autonomously (AGI Loop)

POST /:goalId/execute-autonomous

  • Authentication: Required
  • Parameters:
    • goalId (path): Goal ID
  • Body (optional):
{
  "maxIterations": 50,
  "provider": "anthropic",
  "model": "claude-sonnet-4-20250514"
}
  • Description: Trigger autonomous goal execution. The system iterates through execute → evaluate → re-plan cycles until the goal passes evaluation or reaches maxIterations. Provider/model are forwarded to task execution, evaluation, re-planning, insight extraction, and skill evolution. Broadcasts real-time goal:iteration_* events via WebSocket.
  • Response:
{
  "message": "Autonomous goal execution started",
  "goalId": "goal-id",
  "maxIterations": 50
}

Get Iteration History

GET /:goalId/iterations

  • Authentication: Required
  • Parameters:
    • goalId (path): Goal ID
  • Description: Get the full iteration history for an autonomous goal execution. Each iteration includes evaluation scores and re-planned task data.
  • Response:
{
  "success": true,
  "iterations": [
    {
      "iteration": 1,
      "action": "Description of action taken",
      "result": {},
      "evaluation": {},
      "evaluation_score": 65.5,
      "evaluation_passed": 0,
      "world_state_snapshot": {},
      "replanned_tasks": [],
      "duration_ms": 45000,
      "timestamp": "2024-01-01T00:00:00Z"
    }
  ]
}

Get World State

GET /:goalId/world-state

  • Authentication: Required
  • Parameters:
    • goalId (path): Goal ID
  • Description: Get the current world state snapshot for a goal's autonomous execution
  • Response:
{
  "success": true,
  "worldState": {
    "goalId": "goal-id",
    "currentIteration": 5,
    "state": {},
    "updatedAt": "2024-01-01T00:00:00Z"
  }
}

Revert to Iteration

POST /:goalId/revert/:iteration

  • Authentication: Required
  • Parameters:
    • goalId (path): Goal ID
    • iteration (path): Iteration number to revert to
  • Description: Revert the goal's execution state to a specific iteration
  • Response:
{
  "success": true,
  "revertedToIteration": 3,
  "worldState": {}
}

Review Goal

POST /:id/review

  • Authentication: Required
  • Parameters:
    • id (path): Goal ID
  • Description: Approve or reject a goal that is in needs_review status
  • Body:
{
  "status": "approved|rejected",
  "feedback": "Optional feedback message"
}
  • Response:
{
  "success": true,
  "goal": {
    "id": "goal-id",
    "status": "approved",
    "reviewedAt": "2024-01-01T00:00:00Z"
  }
}

Evaluate Goal

POST /:id/evaluate

  • Authentication: Required
  • Parameters:
    • id (path): Goal ID
  • Body:
{
  "evaluation_type": "automatic",
  "provider": "anthropic",
  "model": "claude-sonnet-4-20250514"
}
  • Description: Evaluate a completed goal using LLM-as-judge. Each task output is scored against its success criteria, then an overall evaluation is produced. Token usage is tracked and stored per evaluation. The goal status is set to validated (score ≥ 70%) or needs_review.
  • Response:
{
  "passed": true,
  "status": "validated",
  "scores": {
    "overall": 85,
    "taskScores": {}
  },
  "feedback": "Detailed evaluation feedback...",
  "input_tokens": 8000,
  "output_tokens": 1500,
  "total_tokens": 9500,
  "estimated_cost": 0.025
}

Get Evaluation Report

GET /:id/evaluation

  • Authentication: Required
  • Parameters:
    • id (path): Goal ID
  • Description: Get evaluation report for a goal
  • Response:
{
  "goalId": "goal-id",
  "evaluations": [
    {
      "timestamp": "2024-01-01T00:00:00Z",
      "score": 85,
      "metrics": {},
      "recommendations": []
    }
  ]
}

Save as Golden Standard

POST /:id/golden-standard

  • Authentication: Required
  • Parameters:
    • id (path): Goal ID
  • Body:
{
  "name": "Golden Standard Name",
  "description": "Description of the golden standard"
}
  • Response:
{
  "success": true,
  "goldenStandard": {
    "id": "golden-standard-id",
    "name": "Golden Standard Name",
    "description": "Description",
    "sourceGoalId": "goal-id",
    "createdAt": "2024-01-01T00:00:00Z"
  }
}

Get Golden Standards

GET /golden-standards/list

  • Authentication: Required
  • Description: Retrieve all golden standards
  • Response:
{
  "goldenStandards": [
    {
      "id": "golden-standard-id",
      "name": "Golden Standard Name",
      "description": "Description",
      "sourceGoalId": "goal-id",
      "createdAt": "2024-01-01T00:00:00Z"
    }
  ]
}

Get All Goals (Summary)

GET /summary

  • Authentication: Required
  • Description: Lightweight goal list — summary rows for rendering lists without loading full task payloads
  • Parameters:
    • includeDeleted (query, optional): true to include soft-deleted goals
  • Response:
{
  "goals": []
}