AbstractGateway — API overview¶
The HTTP API is implemented with FastAPI under the /api prefix:
- Health: GET /api/health
- Gateway surface: /api/gateway/* (durable runs + operator tooling)
The API is documented at runtime:
- OpenAPI JSON: GET /openapi.json
- Swagger UI: GET /docs (use Authorize to paste the bearer token)
Context: - In the AbstractFramework ecosystem, UIs and automations call this API to operate AbstractRuntime runs. - Architecture diagram and core concepts: architecture.md
Auth¶
By default, /api/gateway/* is protected by GatewaySecurityMiddleware (bearer token + origin allowlist).
See: security.md.
All examples below assume:
export BASE_URL="http://127.0.0.1:8080"
export AUTH="Authorization: Bearer $ABSTRACTGATEWAY_AUTH_TOKEN"
Core workflow lifecycle¶
1) List bundles (bundle mode)¶
curl -sS -H "$AUTH" "$BASE_URL/api/gateway/bundles"
Upload a bundle:
curl -sS -H "$AUTH" \
-F "file=@./my-bundle@0.1.0.flow" \
-F "overwrite=false" \
-F "reload=true" \
"$BASE_URL/api/gateway/bundles/upload"
2) Start a run¶
curl -sS -H "$AUTH" -H "Content-Type: application/json" \
-d '{"bundle_id":"my-bundle","input_data":{"prompt":"Hello"}}' \
"$BASE_URL/api/gateway/runs/start"
If you need a specific entrypoint:
curl -sS -H "$AUTH" -H "Content-Type: application/json" \
-d '{"bundle_id":"my-bundle","flow_id":"ac-echo","input_data":{"prompt":"Hello"}}' \
"$BASE_URL/api/gateway/runs/start"
Evidence: request/response models live in src/abstractgateway/routes/gateway.py (StartRunRequest, start_run).
2b) Schedule a run (bundle mode)¶
POST /api/gateway/runs/schedule starts a scheduled parent run that launches the target workflow as child runs over time.
Example (run 3 times, every hour, starting now):
curl -sS -H "$AUTH" -H "Content-Type: application/json" \
-d '{"bundle_id":"my-bundle","flow_id":"ac-echo","input_data":{"prompt":"Ping"},"start_at":"now","interval":"1h","repeat_count":3,"share_context":true,"session_id":"sess-1"}' \
"$BASE_URL/api/gateway/runs/schedule"
Notes:
- start_at: ISO 8601 timestamp (recommended) or "now".
- interval: e.g. "15m", "1h", "2d". If omitted, runs once.
- repeat_count: if omitted and interval is set, repeats forever. Alternatively use repeat_until (ISO 8601).
- To stop a schedule, cancel the scheduled parent run via POST /api/gateway/commands with type cancel.
Evidence: ScheduleRunRequest, start_scheduled_run in src/abstractgateway/routes/gateway.py.
3) Replay the ledger (cursor-based)¶
Ledger pages are replayed using after as “number of items already consumed”.
curl -sS -H "$AUTH" "$BASE_URL/api/gateway/runs/<run_id>/ledger?after=0&limit=200"
Response shape:
- items: list of durable ledger records
- next_after: the next cursor to use
Evidence: src/abstractgateway/routes/gateway.py (get_ledger).
3b) Replay ledgers for multiple runs (batch)¶
Use POST /api/gateway/runs/ledger/batch to reduce request fanout when observing many runs/subflows.
curl -sS -H "$AUTH" -H "Content-Type: application/json" \
-d '{"limit":200,"runs":[{"run_id":"<run_id_1>","after":0},{"run_id":"<run_id_2>","after":0}]}' \
"$BASE_URL/api/gateway/runs/ledger/batch"
Evidence: src/abstractgateway/routes/gateway.py (get_ledger_batch).
4) Stream ledger updates (SSE)¶
SSE is an optimization; clients should always be able to reconnect by replaying from the last next_after.
curl -N -H "$AUTH" "$BASE_URL/api/gateway/runs/<run_id>/ledger/stream?after=0"
Evidence: src/abstractgateway/routes/gateway.py (stream_ledger).
Durable commands (POST /api/gateway/commands)¶
Commands are appended to a durable inbox and applied asynchronously by the runner.
Request fields (see SubmitCommandRequest in src/abstractgateway/routes/gateway.py):
- command_id: client-supplied idempotency key (UUID recommended)
- run_id: target run id (or session id for some event use-cases)
- type: pause|resume|cancel|emit_event|update_schedule|compact_memory
- payload: command-specific object
Pause / cancel¶
curl -sS -H "$AUTH" -H "Content-Type: application/json" \
-d '{"command_id":"'"$(python -c 'import uuid; print(uuid.uuid4())')"'", "run_id":"<run_id>", "type":"pause", "payload":{"reason":"operator_pause"}}' \
"$BASE_URL/api/gateway/commands"
Resume a paused run¶
curl -sS -H "$AUTH" -H "Content-Type: application/json" \
-d '{"command_id":"'"$(python -c 'import uuid; print(uuid.uuid4())')"'", "run_id":"<run_id>", "type":"resume", "payload":{}}' \
"$BASE_URL/api/gateway/commands"
Resume a WAITING run with a payload (WAIT resume)¶
When payload.payload is present, the runner interprets this as “resume a WAITING run with a durable payload”:
curl -sS -H "$AUTH" -H "Content-Type: application/json" \
-d '{"command_id":"'"$(python -c 'import uuid; print(uuid.uuid4())')"'", "run_id":"<run_id>", "type":"resume", "payload":{"wait_key":"<optional_wait_key>", "payload":{"approved":true}}}' \
"$BASE_URL/api/gateway/commands"
Evidence: src/abstractgateway/runner.py (_apply_command, _apply_run_control).
Emit an external event¶
Minimal form:
curl -sS -H "$AUTH" -H "Content-Type: application/json" \
-d '{"command_id":"'"$(python -c 'import uuid; print(uuid.uuid4())')"'", "run_id":"<session_id>", "type":"emit_event", "payload":{"name":"chat.message","payload":{"text":"hi"}}}' \
"$BASE_URL/api/gateway/commands"
Evidence: src/abstractgateway/runner.py (_apply_emit_event).
Beyond the core¶
/api/gateway/* also includes optional operator/tooling endpoints (reports inbox, triage queue, backlog browsing + exec runner, process manager, file/attachment helpers, embeddings, voice, discovery, …).
See: maintenance.md.
Discovery endpoints (optional)¶
These exist to help thin clients adapt to the deployed gateway.
- Capabilities (best-effort):
GET /api/gateway/discovery/capabilities - Providers/models discovery (best-effort):
GET /api/gateway/discovery/providers,GET /api/gateway/discovery/providers/{provider}/models - Dynamic capability catalogs:
GET /api/gateway/voice/voices,GET /api/gateway/audio/speech/models,GET /api/gateway/vision/provider_models
The capabilities payload includes package presence (abstractruntime,
abstractcore, abstractmemory, abstractvoice, abstractvision), existing
gateway helpers (tools, visualflow, media), memory-store readiness, and
AbstractCore capability plugin status for voice, audio, vision, and
future music.
Provider discovery also reports the resolved default provider/model when one is
configured. The resolver follows request values, Gateway env, and AbstractCore
global defaults; if no pair exists, the response includes default_error rather
than a hardcoded local model.
It also includes a versioned thin-client contract:
capabilities.contracts.version: currently1capabilities.contracts.common: shared run start/list/summary/input/history, ledger, artifact, attachment, workspace, discovery, and provider prompt-cache controlscapabilities.contracts.flow_editor: the AbstractFlow editor/runtime surfacecapabilities.contracts.assistant: assistant-facing voice/audio/media/cache feature gatescapabilities.contracts.abstractcode: code-client run/history/workspace/cache feature gates
Contract booleans are intentionally conservative. Package installed=true is
not the same thing as endpoint available=true; clients should branch on the
versioned contract fields when enabling controls.
Evidence: src/abstractgateway/routes/gateway.py (discovery_capabilities, discovery_providers).
AbstractFlow gateway-first editor contract¶
The browser editor can use AbstractGateway as its runtime and storage host.
Draft VisualFlow records:
GET /api/gateway/visualflowsPOST /api/gateway/visualflowsGET /api/gateway/visualflows/{flow_id}PUT /api/gateway/visualflows/{flow_id}DELETE /api/gateway/visualflows/{flow_id}POST /api/gateway/visualflows/{flow_id}/publish
Bundle inspection and editor run-schema helpers:
GET /api/gateway/bundlesGET /api/gateway/bundles/{bundle_id}GET /api/gateway/bundles/{bundle_id}/flows/{flow_id}GET /api/gateway/bundles/{bundle_id}/flows/{flow_id}/input_schema
The input-schema endpoint returns a versioned payload with:
versionbundle_id,bundle_version,bundle_ref,flow_id,workflow_idinputs: entrypoint input pins derived from theon_flow_startnodedefaults: pin defaults from VisualFlow JSONinput_data_schema: a small JSON Schema object for the Run Flow modal
Example:
curl -sS -H "$AUTH" \
"$BASE_URL/api/gateway/bundles/my-bundle/flows/ac-echo/input_schema"
The editor observes runs with the core lifecycle endpoints above:
/runs/start, /runs/{run_id}, /runs/{run_id}/ledger,
/runs/{run_id}/ledger/stream, /runs/ledger/batch,
/runs/{run_id}/input_data, /runs/{run_id}/history_bundle, and
/runs/{run_id}/artifacts.
Optional multimodal scope¶
Direct Gateway endpoints in this release:
- POST /api/gateway/runs/{run_id}/voice/tts
- POST /api/gateway/runs/{run_id}/audio/transcribe
- POST /api/gateway/runs/{run_id}/images/generate
- GET /api/gateway/voice/voices
- GET /api/gateway/audio/speech/models
- GET /api/gateway/vision/provider_models
The catalog endpoints proxy AbstractCore Server routes when
ABSTRACTGATEWAY_ABSTRACTCORE_SERVER_BASE_URL or ABSTRACTCORE_SERVER_BASE_URL
is configured. Gateway uses explicit Core auth settings for that hop and never
reuses the Gateway bearer token as a Core/provider secret. Without a configured
Core server, the voice/model routes return bounded static descriptors from
Gateway and capability-package environment variables.
Generated images are available through Runtime/Core workflows when
AbstractVision is installed and configured. Gateway also exposes a direct image
generation endpoint that uses the Runtime/Core output-selector contract rather
than a provider-specific image client. The route stores the generated image as a
run artifact and emits abstract.media.image.generated with:
run_id,request_id,prompt- optional
provider,model,size,width,height, andformat image_artifact:{"$artifact", "content_type", "filename", "sha256", "size_bytes"}
If the active workflow runtime already has an AbstractCore LLM client, the route
uses it. For tools-only workflows, the route can create a direct Runtime/Core
client from request provider/model or ABSTRACTGATEWAY_PROVIDER /
ABSTRACTGATEWAY_MODEL. Unsupported or unconfigured deployments return a
structured ok=false response instead of a failed run.
KG memory¶
POST /api/gateway/kg/query queries the configured AbstractMemory TripleStore.
Gateway resolves the store through:
ABSTRACTGATEWAY_MEMORY_STORE_BACKEND=lancedb|memory(sqlitewhen the installed AbstractMemory build exposesSQLiteTripleStore)ABSTRACTGATEWAY_MEMORY_STORE_PATHABSTRACTGATEWAY_MEMORY_REQUIRE_VECTOR
Structured queries work with LanceDB and in-memory stores. SQLite also works
when the installed AbstractMemory build exposes SQLiteTripleStore. Semantic
query_text requires a vector-capable backend plus configured Gateway
embeddings; SQLite returns a clear 400 instead of pretending to support semantic
recall.
Prompt-cache control plane (operator API)¶
The gateway exposes prompt-cache operator endpoints under /api/gateway/prompt_cache/*.
Core endpoints:
GET /api/gateway/prompt_cache/capabilities?provider=...&model=...GET /api/gateway/prompt_cache/stats?provider=...&model=...POST /api/gateway/prompt_cache/setPOST /api/gateway/prompt_cache/updatePOST /api/gateway/prompt_cache/forkPOST /api/gateway/prompt_cache/clearPOST /api/gateway/prompt_cache/prepare_modules
Behavior:
- These routes use the runtime's AbstractCore prompt-cache client contract rather than directly depending on provider-instance access.
- In local mode they delegate to the in-process provider.
- In remote/hybrid mode they follow whatever
/acore/prompt_cache/*surface the configured AbstractCore server exposes. - All core prompt-cache responses include
operationandcapabilities, with structured unsupported/error cases (code="prompt_cache_unsupported"/code="prompt_cache_error"/code="prompt_cache_unavailable"). - These endpoints remain provider/model controls, not a Gateway-owned CachedSession persistence system.
Session lifecycle endpoints:
GET /api/gateway/sessions/{session_id}/prompt_cache/statusPOST /api/gateway/sessions/{session_id}/prompt_cache/preparePOST /api/gateway/sessions/{session_id}/prompt_cache/rebuildPOST /api/gateway/sessions/{session_id}/prompt_cache/clear
These routes derive a deterministic bounded namespace/key from session_id,
bundle_id, bundle_version, flow_id, provider, model, optional
template_id, and version. They expose three honest modes:
unsupported: provider/model does not expose prompt-cache support; responses includesupported=false,ok=false, and capabilities.keyed: gateway returns a stableruntime_hint/prompt_cache_keyfor Runtime/Core injection, but does not claim module preparation occurred.local_control_plane: gateway uses supported provider operations such asprepare_modules,fork,set,clear, andstats.
status is read-only. prepare accepts optional modules (system_prompt,
workflow_instructions, tools, pinned_attachments) and returns either
provider operation results or a key hint. rebuild is clear-plus-prepare for
providers that expose clear controls.
Provider-specific persistence endpoints:
GET /api/gateway/prompt_cache/savedPOST /api/gateway/prompt_cache/savePOST /api/gateway/prompt_cache/load
These remain explicitly local/provider-specific in this release:
save/loadrequire direct local provider access.- Currently intended for in-process
mlxandhuggingfaceGGUF (llama.cpp) workers only. - GGUF save/load preserves both the raw llama.cpp cache and provider-side prompt-cache metadata so reloaded cache keys keep their module/history meaning.
Email inbox (operator UI; optional)¶
These endpoints power AbstractObserver’s Inbox → Email UI. They are account-scoped: the browser cannot supply arbitrary IMAP/SMTP host/user credentials. The gateway host must be configured with one or more email accounts (multi-account YAML or env vars).
Endpoints:
- GET /api/gateway/email/accounts
- GET /api/gateway/email/messages?account=…&mailbox=…&since=…&status=…&limit=…
- GET /api/gateway/email/messages/{uid}?account=…&mailbox=…&max_body_chars=…
- POST /api/gateway/email/send
Examples:
curl -sS -H "$AUTH" "$BASE_URL/api/gateway/email/accounts"
curl -sS -H "$AUTH" "$BASE_URL/api/gateway/email/messages?status=unread&since=7d&limit=20"
curl -sS -H "$AUTH" "$BASE_URL/api/gateway/email/messages/12345?max_body_chars=20000"
curl -sS -H "$AUTH" -H "Content-Type: application/json" \
-d '{"to":"you@example.com","subject":"Hello","body_text":"Hi!"}' \
"$BASE_URL/api/gateway/email/send"
Configuration notes (gateway host):
- Multi-account: set ABSTRACT_EMAIL_ACCOUNTS_CONFIG=/path/to/emails.yaml (recommended).
- Single-account env fallback: set ABSTRACT_EMAIL_IMAP_* and/or ABSTRACT_EMAIL_SMTP_*.
- The secret itself must be present in the env var referenced by *_PASSWORD_ENV_VAR (e.g. EMAIL_PASSWORD=...).
Evidence: src/abstractgateway/routes/gateway.py (/email/accounts|messages|send) which proxies to abstractcore.tools.comms_tools.
Troubleshooting and common questions: faq.md.