AgentOS Read Endpoints
Inspect runs, replay sessions, and list approval requirements over HTTP
AgentOS can list and inspect past runs, replay a session’s transcript, and list which tools require approval — all over HTTP, with 503 (not an empty list) when the underlying store is missing.
Quick Start
- Attach a ledger and serve
Attaching a
SQLiteRunLedgerunlocks/api/runsand/api/runs/{run_id}.python from praisonai import AgentOS from praisonaiagents import Agent from praisonaiagents.runs import SQLiteRunLedger app = AgentOS(agents=[Agent(instructions="Be helpful")]) app.run_ledger = SQLiteRunLedger() # unlocks /api/runs and /api/runs/{id} app.serve(port=8000) - Read runs over HTTP
bash curl http://localhost:8000/api/runs?limit=10 curl http://localhost:8000/api/runs/<run_id>
Enabling Each Endpoint
Each endpoint reads a store you attach to the AgentOS instance.
Runs
Attach a run ledger to expose /api/runs and /api/runs/{run_id}.
from praisonaiagents.runs import SQLiteRunLedger
app.run_ledger = SQLiteRunLedger()See Run Ledger.
Sessions
Attach a session store with recent(), get_chat_history(), and optionally session_exists() to expose /api/sessions and /api/sessions/{session_id}.
from praisonaiagents.session import DefaultSessionStore
app.session_store = DefaultSessionStore()Approvals
No attribute needed. /api/approvals reads the process-global registry populated by add_approval_requirement(...) / require_approval(...).
from praisonaiagents.approval import add_approval_requirement
add_approval_requirement("delete_file", risk_level="high")See Approval Protocol.
Endpoint Reference
Five read-only routes, each returning 503 naming what to configure when its store is absent.
| Method | Path | Purpose | Missing-store behaviour |
|---|---|---|---|
| GET | /api/runs?limit=50 | List runs from the attached ledger. limit bounded 1 ≤ limit ≤ 500. | 503 — no run ledger configured; attach a SQLiteRunLedger as run_ledger. |
| GET | /api/runs/{run_id} | Fetch a single run. | 503 if no ledger; 404 if the ledger returns None for that id. |
| GET | /api/sessions?limit=20 | List recent sessions. limit bounded 1 ≤ limit ≤ 200. | 503 if session_store is unset or lacks recent(). |
| GET | /api/sessions/{session_id}?limit=100 | Return the transcript for one session. limit bounded 1 ≤ limit ≤ 500. | 503 if no store; 404 if session_exists(session_id) is False, or the store has no session_exists() and the transcript is empty. |
| GET | /api/approvals | List global + per-agent approval requirements. | 503 if praisonaiagents.approval is not installed or the registry exposes no requirement listing. |
Response Shapes
Every response matches the endpoint’s contract exactly.
GET /api/runs
Each run is the record’s own as_dict() (or vars()) — ledgers with extra fields are not truncated.
{ "runs": [ { "run_id": "r1", "status": "done" } ], "count": 1 }GET /api/runs/{run_id}
The record’s dict directly — no wrapper.
{ "run_id": "r1", "status": "done", "agent": "researcher" }GET /api/sessions
{ "sessions": [ { "session_id": "s1", "messages": 4 } ], "count": 1 }GET /api/sessions/{session_id}
The chat history as the store returns it.
{ "session_id": "s1", "messages": [ { "role": "user", "content": "hi" } ] }GET /api/approvals
{ "requirements": [ { "tool": "delete_file", "agent": null, "risk_level": "high" } ] }Why the Errors Look Like This
Choosing an Endpoint
This decision diagram maps a question to the endpoint that answers it.
How Operators Interact
An operator lists runs; the ledger either answers or the endpoint says what to attach.
Best Practices
Attach a ledger in production
The 503 names what to attach, but you want the endpoint to actually work. Attach a SQLiteRunLedger before deploying.
Treat 503 as a config bug, not a request bug
A 503 means the store is missing, not that the request was malformed. Do not retry it — fix the configuration.
Read-only on purpose
Mutating a run over HTTP is a much larger design question. Use the SDK for changes; these endpoints only read.
Keep limit conservative
The upper bounds (runs ≤ 500, sessions ≤ 200) exist because clients can otherwise ask for a full-table scan. Request only what you need.