Agents API
Cloud-Agenten per REST erstellen, steuern und beobachten — dieselbe API, die den Outgate-Chat antreibt.
Überblick
Alles, was der Chat kann, kann auch Ihr Code: eine REST-Oberfläche für die gesamte Agenten-Plattform.
Die Agents API stellt die Agenten-Plattform auf https://api.outgate.ai unter /api/v1/agents bereit. Sie ist keine Seitentür mit einem Teil der Features — der Outgate-Chat ist auf genau diesen Endpoints gebaut, alles aus der UI lässt sich also automatisieren.
POST /api/v1/agents/threads create an agent
POST .../threads/{id}/events send a message
GET .../threads/{id}/events read what happened
GET <region events url>?wait=25 follow live output (long-poll)
POST /api/v1/agents/webhooks get notified without pollingDie typische Integration ist klein: Thread erstellen, Eingabe senden, Events bis zum Abschluss des Turns verfolgen, Ergebnis lesen. Webhooks ersetzen Polling bei Fire-and-forget-Automatisierung.
Authentifizierung und Scopes
API-Keys mit expliziten Read-/Write-Scopes; ein konsistenter Error-Envelope.
Erstellen Sie einen API-Key in der Console. Keys tragen das Präfix gw_ und werden nur einmal bei der Erstellung angezeigt. Senden Sie den Key als Bearer-Token bei jedem Request mit.
curl https://api.outgate.ai/api/v1/agents/regions \
-H "Authorization: Bearer gw_your_key"| Scope | Erlaubt |
|---|---|
| outgate.agents.read | Threads auflisten und inspizieren, Event-Historie lesen, Modelle, Configs und Regionen auflisten. |
| outgate.agents.write | Threads erstellen, steuern und löschen; Workspaces, Webhooks und Provider-Anmeldung verwalten. |
Jeder Fehler auf jedem Agents-Endpoint nutzt denselben Envelope: ein error-Objekt mit einem stabilen, maschinenlesbaren Code und einer menschenlesbaren Message. Matchen Sie auf den Code, nicht auf die Message.
{
"error": {
"code": "thread_not_found",
"message": "No thread with this id exists in your organization."
}
}Requests sind pro Organisation gemäß Ihrem Plan rate-limitiert; Antworten enthalten X-RateLimit-Header, damit Clients sich selbst takten können.
Einen Thread erstellen
Die Erstellung ist asynchron: Sie erhalten sofort einen Thread, die Sandbox ist Sekunden später live.
Ermitteln Sie zuerst, was Ihre Organisation ausführen kann: GET /api/v1/agents/configs listet die verfügbaren Agent-Konfigurationen (jede legt Agent-Typ, Region und Sandbox-Ressourcen fest), GET /api/v1/agents/regions listet die Regionen. Dann erstellen Sie den Thread.
curl -X POST https://api.outgate.ai/api/v1/agents/threads \
-H "Authorization: Bearer gw_your_key" \
-H "Content-Type: application/json" \
-d '{
"agentConfigId": "acfg-example",
"metadata": { "ticket": "OPS-1423" }
}'{
"threadId": "6f9d2c1e-...",
"status": "starting",
"tool": "claude",
"regionId": "de-west-1",
"ephemeral": true,
"expiresAt": null,
"events": {
"url": "https://<region>/v1/agents/threads/6f9d2c1e-.../events",
"token": "<consumer token>",
"expiresAt": "2026-07-11T10:00:00Z"
}
}Die Antwort kommt sofort mit Status starting; das Sandbox-Provisioning läuft im Hintergrund weiter. Pollen Sie GET /api/v1/agents/threads/{threadId}, bis der Status live ist, oder beobachten Sie die Events-URL — ein Lifecycle-Event meldet spawned oder spawn_failed, Fehlschläge sind also explizit statt still.
| Feld | Bedeutung |
|---|---|
| agentConfigId | Erforderlich. Welche Agent-Konfiguration ausgeführt wird (aus GET /configs). |
| regionId | Optional. Standard ist die Region der Konfiguration. |
| workspaceId | Optional. Hängt ein persistentes Workspace-Volume an. Weglassen für einen ephemeren Thread mit reinem Scratch-Speicher. |
| ttlSeconds | Optionale begrenzte Thread-Lebensdauer in Sekunden: 0 (läuft nie ab), 60, 300, 3600, 28800, 86400 oder 2592000. Weglassen, um die Region-Standardeinstellung zu verwenden — Threads auf von Outgate verwalteten Regionen sind standardmäßig langlebig, daher kommt expiresAt als null zurück. |
| idleTimeoutSeconds | Optional. Wie lange die Sandbox ohne Aktivität aktiv bleibt, bevor sie schläft (60–86400). |
| permissionMode | ask (Agent bittet um Freigabe für Tools) oder skip (autonom). |
| effort | Reasoning-Effort: low, medium, high, xhigh oder max. |
| metadata | Bis zu 4 KB eigenes JSON, am Thread gespeichert und bei Reads zurückgegeben. |
Threads lassen sich nach der Erstellung ändern: PATCH /api/v1/agents/threads/{threadId} ändert Modell, Effort oder Permission-Modus (die Sandbox startet an Ort und Stelle neu, die Konversation bleibt erhalten), POST .../resume weckt einen Idle-Thread explizit, und DELETE baut ihn ab.
Eingaben senden
Posten Sie Events an den Thread: Text, Interrupts, Permission-Antworten, Titel.
curl -X POST https://api.outgate.ai/api/v1/agents/threads/{threadId}/events \
-H "Authorization: Bearer gw_your_key" \
-H "Content-Type: application/json" \
-d '{
"kind": "input.text",
"payload": { "text": "Run the test suite and summarize the failures." },
"correlation_id": "my-req-42"
}'| Kind | Payload | Wirkung |
|---|---|---|
| input.text | { "text": "..." } | Eine Nutzernachricht. Weckt die Sandbox, falls sie idle ist. |
| interrupt | {} | Stoppt den aktuellen Turn des Agenten. |
| permission_response | { "granted": true } | Beantwortet einen ausstehenden permission_request. |
| thread.title | { "title": "..." } | Benennt den Thread um. |
Die Antwort enthält die Sequenznummer und den Zeitstempel des angehängten Events. Wenn Sie eine correlation_id (bis zu 128 Zeichen) übergeben, wird sie auf dem kanonischen Event zurückgespiegelt, damit optimistische UIs ihre lokale Kopie mit dem Stream abgleichen können.
Nur diese Consumer-Kinds werden akzeptiert; servergenerierte Kinds werden mit einem forbidden_kind-Fehler abgelehnt — ein fehlerhafter Client kann also keine Agenten-Ausgabe fälschen.
Events lesen
Die vollständige Thread-Historie ist ein geordnetes, filterbares Event-Log.
Alles, was auf einem Thread passiert — Nutzereingaben, Agenten-Text, Tool-Aufrufe, Lifecycle-Übergänge — ist ein Event mit monoton steigender Sequenznummer. GET /api/v1/agents/threads/{threadId}/events liest das Log.
| Query-Parameter | Bedeutung |
|---|---|
| since / until | Sequenznummern-Grenzen für die Seite. |
| limit | Maximale Anzahl zurückgegebener Events; nextCursor setzt die Seite fort. |
| kinds | Kommagetrennter Filter, z. B. kinds=text_delta,turn_complete. |
| reverse=true | Neueste zuerst — mit limit kombinieren, um die letzte Aktivität zu holen. |
| from / to | Zeitstempel-Grenzen als ISO 8601. |
Die neuesten Events abrufen
Das Log wird standardmäßig älteste zuerst zurückgegeben. Um zu zeigen, "was gerade passiert ist", nutzen Sie reverse=true mit einem limit und sortieren clientseitig um — pagen Sie nicht bei jedem Refresh ab Sequenz null.
{
"events": [
{ "seq": 41, "ts": "2026-07-11T09:14:03Z", "kind": "input.text",
"payload": { "text": "Run the test suite..." } },
{ "seq": 42, "ts": "2026-07-11T09:14:09Z", "kind": "text_delta",
"payload": { "text": "Running pytest..." } },
{ "seq": 57, "ts": "2026-07-11T09:15:40Z", "kind": "turn_complete",
"payload": {} }
],
"nextCursor": null,
"thread": { "id": "6f9d2c1e-...", "maxSeq": 57 }
}Live-Ausgabe verfolgen
Long-Poll auf den regionsdirekten Events-Endpoint für Streaming mit niedriger Latenz.
Für Live-Ausgabe nutzen Sie die regionsdirekte Events-URL, die bei der Thread-Erstellung zurückgegeben wurde. Sie liefert dasselbe Event-Log, unterstützt aber einen wait-Parameter: Der Request blockiert, bis neue Events eintreffen oder das Fenster abläuft — Zustellung unter einer Sekunde, ohne Websocket.
# events.url und events.token stammen aus der Thread-Erstellung
curl "$EVENTS_URL?since=$LAST_SEQ&wait=25" \
-H "Authorization: Bearer $EVENTS_TOKEN"- wait akzeptiert bis zu 25 Sekunden. Ein leeres events-Array nach Ablauf des Fensters ist normal — stellen Sie den Request einfach mit demselben Cursor erneut.
- Das Events-Token ist auf diesen einen Thread gescoped und läuft ab; POST /api/v1/agents/threads/{threadId}/events-token rotiert es (das alte Token wird widerrufen).
- Bei einem 401 vom Region-Endpoint rotieren Sie das Token und versuchen es erneut — das ist der normale Recovery-Pfad, kein Fehlerzustand.
Die Schleife: Request mit der zuletzt gesehenen Sequenznummer und wait=25 stellen, das Ergebnis anwenden, Cursor aktualisieren, wiederholen. Zusammen mit der asynchronen Erstellung ergibt das einen vollständig event-getriebenen Client mit zwei beweglichen Teilen.
Webhooks
Einmal abonnieren, signierte Benachrichtigungen für die Momente erhalten, die zählen.
Wenn Sie keinen Long-Poll offen halten wollen, abonnieren Sie Ihren Endpoint auf grobkörnige Thread-Events. Outgate postet für jedes Vorkommen über alle Threads Ihrer Organisation hinweg eine signierte Zustellung.
curl -X POST https://api.outgate.ai/api/v1/agents/webhooks \
-H "Authorization: Bearer gw_your_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://ops.example.com/hooks/outgate",
"events": ["lifecycle", "error", "turn_complete", "permission_request"]
}'Die Antwort enthält ein whsec_-Signing-Secret — einmal angezeigt, später nie wieder abrufbar. Abonnierbare Kinds sind lifecycle, error, turn_complete, permission_request sowie die App-Run-Kinds app.run und app.run_result. Eine Organisation kann bis zu 10 Abonnements halten.
Jede Zustellung trägt den Event-Kind in X-Outgate-Event und eine HMAC-SHA256-Signatur des rohen Bodys in X-Outgate-Signature. Verifizieren Sie, bevor Sie vertrauen:
import crypto from 'node:crypto';
function verify(rawBody, signatureHeader, secret) {
const expected = crypto.createHmac('sha256', secret)
.update(rawBody).digest('hex');
const got = signatureHeader.replace(/^sha256=/, '');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(got));
}- Zustellungen laufen nach 5 Sekunden in den Timeout und werden bei Netzwerkfehlern oder 5xx einmal wiederholt — halten Sie Ihren Handler schnell und idempotent.
- Ein fehlschlagender Endpoint blockiert nie den Agenten oder andere Abonnements.
- Beantworten Sie permission_request-Zustellungen, indem Sie ein permission_response-Event an den Thread posten — das schließt den Kreis für vollautonome Freigabe-Policies.
Modelle und Provider-Anmeldung
Den Live-Modellkatalog inspizieren und die Provider-Anmeldung programmatisch abschließen.
GET /api/v1/agents/threads/{threadId}/models liefert den Modellkatalog so, wie die Sandbox ihn tatsächlich sieht — die Modelle, die Ihr Provider-Account anbietet, frisch vom Provider aktualisiert. Kombinieren Sie ihn mit PATCH auf dem Thread, um das Modell zu wechseln.
Die Provider-Anmeldung — der Connect-Claude-/Connect-ChatGPT-Flow aus dem Chat — ist ebenfalls verfügbar: POST .../login startet den Flow und liefert die URL, die der Nutzer bestätigen muss; POST .../login/code übermittelt den resultierenden Code; GET .../auth meldet, ob der Thread angemeldet ist; POST .../logout löscht die Session. Damit betten Sie Agenten-Onboarding in Ihr eigenes Produkt ein, ohne Nutzer zum Outgate-Chat zu schicken.
Dateien und Git
Den Workspace inspizieren und Git-Operationen gegen echte Repositories ausführen.
GET /api/v1/agents/threads/{threadId}/files listet Workspace-Inhalte (übergeben Sie path, um in Verzeichnisse abzusteigen). Es ist dieselbe Ansicht wie der Files-Tab im Chat.
POST /api/v1/agents/threads/{threadId}/git führt einen Git-Befehl in der Sandbox aus:
{
"cmd": "clone",
"args": ["https://github.com/acme/service.git", "."],
"auth": { "token": "<token for private repos>" }
}Die Antwort enthält stdout, stderr und den Exit-Code. So übergebene Tokens werden nur für die eine Operation genutzt und nicht in der Sandbox gespeichert. Für GitHub-Repositories, die eine Installation der Outgate GitHub App abdeckt, erhalten Agenten automatisch kurzlebige, gescopte Tokens — es muss gar kein Token übergeben werden.
Workspaces
Die persistenten Volumes erstellen und verwalten, die Threads unter /workspace mounten.
Workspaces sind benannte persistente Volumes, die in einer Region liegen. Erstellen Sie eines und übergeben Sie seine ID als workspaceId beim Erstellen von Threads — jeder Thread, der es mountet, sieht dieselben /workspace-Inhalte. Lassen Sie workspaceId weg, erhalten Sie stattdessen einen ephemeren Thread.
# Workspace-Routen werden pro Region adressiert
curl -X POST https://api.outgate.ai/api/v1/agents/workspaces \
-H "Authorization: Bearer gw_your_key" \
-H "X-Region-Id: de-west-1" \
-H "Content-Type: application/json" \
-d '{ "workspaceId": "ci-nightly" }'- Workspace-IDs sind Kleinbuchstaben-Slugs (Buchstaben, Ziffern, Bindestriche, Unterstriche; bis zu 64 Zeichen).
- GET /api/v1/agents/workspaces/{workspaceId} meldet die aktuelle Größe in Bytes.
- DELETE entfernt das Volume samt Inhalt — Threads, die es gerade mounten, sollten zuerst beendet werden.
- Alle Workspace-Routen erfordern den X-Region-Id-Header, weil Volumes physische Ressourcen in einer Region sind.
Routen-Referenz
Die komplette v1-Oberfläche auf einen Blick.
| Methode | Pfad | Scope |
|---|---|---|
| POST | /api/v1/agents/threads | write |
| GET | /api/v1/agents/threads | read |
| GET | /api/v1/agents/threads/{id} | read |
| PATCH | /api/v1/agents/threads/{id} | write |
| DELETE | /api/v1/agents/threads/{id} | write |
| POST | /api/v1/agents/threads/{id}/resume | write |
| POST | /api/v1/agents/threads/{id}/events | write |
| GET | /api/v1/agents/threads/{id}/events | read |
| POST | /api/v1/agents/threads/{id}/events-token | write |
| GET | /api/v1/agents/threads/{id}/models | read |
| POST | /api/v1/agents/threads/{id}/login | write |
| POST | /api/v1/agents/threads/{id}/login/code | write |
| POST | /api/v1/agents/threads/{id}/logout | write |
| GET | /api/v1/agents/threads/{id}/auth | read |
| GET | /api/v1/agents/threads/{id}/files | read |
| POST | /api/v1/agents/threads/{id}/git | write |
| GET | /api/v1/agents/threads/{id}/apps | read |
| GET | /api/v1/agents/threads/{id}/apps/{appId} | read |
| POST | /api/v1/agents/threads/{id}/apps/{appId}/run | write |
| POST | /api/v1/agents/threads/{id}/apps/{appId}/unpublish | write |
| PATCH | /api/v1/agents/threads/{id}/apps/{appId} | write |
| DELETE | /api/v1/agents/threads/{id}/apps/{appId} | write |
| GET | /api/v1/agents/threads/{id}/apps/{appId}/secrets | read |
| PUT | /api/v1/agents/threads/{id}/apps/{appId}/secrets/{name} | write |
| DELETE | /api/v1/agents/threads/{id}/apps/{appId}/secrets/{name} | write |
| GET | /api/v1/agents/threads/{id}/apps/{appId}/webhooks | read |
| POST | /api/v1/agents/workspaces | write |
| GET | /api/v1/agents/workspaces/{id} | read |
| DELETE | /api/v1/agents/workspaces/{id} | write |
| GET | /api/v1/agents/configs | read |
| GET | /api/v1/agents/regions | read |
| POST | /api/v1/agents/webhooks | write |
| GET | /api/v1/agents/webhooks | read |
| DELETE | /api/v1/agents/webhooks/{id} | write |
| POST | /api/v1/hooks/apps/{appId} | Hook-Token |
Fehler und Status
Stabile maschinenlesbare Codes für jeden Fehlerfall.
| HTTP | Code | Bedeutung |
|---|---|---|
| 400 | invalid_request | Fehlerhafter Body, fehlendes Feld oder ungültiger Enum-Wert; details listet die Felder auf. |
| 400 | forbidden_kind | Der Event-Kind ist servergeneriert und kann von Consumern nicht gepostet werden. |
| 401 | unauthorized | Fehlende, ungültige oder widerrufene Zugangsdaten. |
| 403 | forbidden | Der Key ist gültig, hat aber nicht den erforderlichen Scope. |
| 404 | thread_not_found | Kein solcher Thread in Ihrer Organisation (organisationsübergreifender Zugriff liest sich ebenfalls als 404). |
| 409 | thread_lost | Die Sandbox existiert nicht mehr; erstellen Sie einen neuen Thread. |
| 409 | run_in_flight | Auf diesem Thread läuft bereits ein App-Run. |
| 502 | region_unavailable | Die Region hat den Befehl nicht angenommen; mit Backoff erneut versuchen. |
| 504 | region_timeout | Die Region hat nicht innerhalb des Befehlsfensters geantwortet; mit Backoff erneut versuchen. |
| Thread-Status | Bedeutung |
|---|---|
| starting | Sandbox-Provisioning läuft; Eingaben werden noch nicht angenommen. |
| live | Der Agent läuft und nimmt Eingaben an. |
| idle | Die Sandbox schläft; der Zustand ist intakt, die nächste Nachricht weckt sie. |
| ended | Der Thread ist abgelaufen oder wurde gelöscht; seine Sandbox ist weg. |