Local API
Automate Theron from your own scripts: create projects, start tasks and answer their questions, create, fill and read task lists, and react to what happens – e.g. a script that syncs a Trello board with Theron, or one that creates tasks from incoming tickets.
Enable
Theron → Settings → Local API: tick Enable local API, choose a port (default 8767),
copy the token and save. The API runs while the app runs.
- Only reachable from this computer (
127.0.0.1). Requests with anotherHostheader are refused, so web pages can't reach it. - Every request needs the header
Authorization: Bearer <token>. Regenerate invalidates the old token. - Requests and answers are JSON (
Content-Type: application/json). Errors come as{"error": "…"}with 400 (invalid input), 401 (token), 404 (unknown id), 409 (not possible right now, e.g. the project has no process or the task has no open question). - Input via the API counts as local input – like typing in the app. Messages are shown as “Local API” in the chat.
export THERON=http://127.0.0.1:8767/v1 THERON_TOKEN=… curl -H "Authorization: Bearer $THERON_TOKEN" $THERON/status
Endpoints
| Method & path | What it does |
|---|---|
GET /status | Version and the id of the newest event. |
GET /processes | Processes (id, name, steps) – for process_id. |
GET /projectsPOST /projects | List / create a project:
{name, description?, rules?, workspace?, process_id?}. workspace is an absolute
path and is created if missing. |
GET /projects/{id}PATCH /projects/{id} | Read / change single fields. |
GET /projects/{id}/tasks | The project's tasks, newest first. |
POST /projects/{id}/tasks | Start a task: {text, title?} – or
{tasklist_id} to work through a task list. Needs a process with at least one step. |
GET /tasks/{id}?events=50 | Status (running, waiting_input,
done, failed, stopped), summary, goal_reached,
the open question in pending_input and optionally the latest events. |
POST /tasks/{id}/messages | Send a message to Theron: {text}. |
POST /tasks/{id}/answer | Answer the open question: {text, request_id?}
(one of pending_input.options or free text). |
POST /tasks/{id}/stop | Stop – {"soon": true} lets the running steps finish first. |
GET /projects/{id}/tasklists | Task lists with progress. |
POST /projects/{id}/tasklists | Create a task list, optionally with epics and requirements in one go (see below). |
GET /tasklists/{id}PATCH · DELETE | The full list: epics in execution order with their requirements, status, result and protocol. |
POST /tasklists/{id}/epics | Add an epic: {name, description?, depends_on?,
requirements?}. |
POST /tasklists/{id}/start | Start a task that works through the list. |
GET /epics/{id}PATCH · DELETE | Epic: name,
description, depends_on, closed. |
POST /epics/{id}/requirements | Add a requirement: {title, description?,
acceptance?, tech_rules?, depends_on?}. |
GET /requirements/{id}PATCH · DELETE | Requirement –
status: open, in_progress, hitl, done, failed, skipped, closed; also
result. |
GET /events | Event stream with long polling – see below. |
All paths start with /v1. depends_on is a list of epic or requirement ids
that have to be done first.
Create a filled task list
curl -X POST $THERON/projects/3/tasklists -H "Authorization: Bearer $THERON_TOKEN" \
-H "Content-Type: application/json" -d '{
"name": "Sprint 12",
"epics": [{"name": "Checkout", "requirements": [
{"title": "Pay with PayPal", "acceptance": "Payment is booked, order confirmed"},
{"title": "Invoice as PDF"}]}]}'
Events
GET /events?since=<id>&wait=30 returns the events after since (oldest first)
and next – pass it as since in the next call. With wait (max. 60 s) the
request waits until something happens. since=-1 starts with what happens from now on. Filters:
project, task, types=a,b.
| Type | Meaning |
|---|---|
status | Task status changed (status, phase). |
input_request | Theron asks: request_id, question, options, recommended. |
input_resolved | A question was answered. |
complete | Task finished: summary, goal_reached. |
requirement_start · requirement_status · requirement_done |
Task list progress, with requirement_id (and success when done). |
alert | ⚑ message from the process (level, text, stop). |
orchestrator · user | Chat messages. |
agent_start · agent_end · handover | Agent steps. |
Example: sync with Trello (Python)
Cards of a Trello list become requirements; when Theron finishes one, the card moves to “Done”. Only the standard library is needed; the Trello calls are left as functions to fill in.
import json, os, urllib.request
API, TOKEN = "http://127.0.0.1:8767/v1", os.environ["THERON_TOKEN"]
def theron(method, path, body=None):
req = urllib.request.Request(API + path, method=method, data=json.dumps(body).encode() if body else None,
headers={"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=90) as r:
return json.load(r)
cards = trello_cards("To do") # your Trello call: [{"id", "name", "desc"}, …]
tl = theron("POST", "/projects/3/tasklists", {"name": "Trello", "epics": [{"name": "Board", "requirements": [
{"title": c["name"], "description": c["desc"]} for c in cards]}]})
card_of = {r["id"]: c["id"] for c, r in zip(cards, tl["epics"][0]["requirements"])} # same order
task = theron("POST", f"/tasklists/{tl['id']}/start", {})
since = theron("GET", "/status")["last_event"]
while True:
page = theron("GET", f"/events?since={since}&wait=60&task={task['id']}")
since = page["next"]
for ev in page["events"]:
if ev["type"] == "requirement_done" and ev["success"]:
trello_move(card_of[ev["requirement_id"]], "Done")
elif ev["type"] == "input_request":
print("Theron asks:", ev["question"], ev["options"]) # answer: POST /tasks/{id}/answer
elif ev["type"] == "complete":
raise SystemExit(ev["summary"])
Lokale API
Steuere Theron aus eigenen Skripten: Projekte anlegen, Tasks starten und ihre Rückfragen beantworten, Task-Listen anlegen, befüllen und lesen und auf Ereignisse reagieren – z. B. ein Skript, das ein Trello-Board mit Theron synchronisiert, oder eines, das aus eingehenden Tickets Tasks erzeugt.
Aktivieren
Theron → Einstellungen → Lokale API: Lokale API aktivieren anhaken, Port wählen (Standard
8767), Token kopieren und speichern. Die API läuft, solange die App läuft.
- Nur von diesem Rechner erreichbar (
127.0.0.1). Anfragen mit anderemHost-Header werden abgewiesen – Webseiten kommen also nicht heran. - Jede Anfrage braucht den Header
Authorization: Bearer <Token>. Neu erzeugen macht den alten Token ungültig. - Anfragen und Antworten sind JSON (
Content-Type: application/json). Fehler kommen als{"error": "…"}mit 400 (ungültige Eingabe), 401 (Token), 404 (unbekannte ID), 409 (gerade nicht möglich, z. B. Projekt ohne Prozess oder keine offene Rückfrage). - Eingaben über die API gelten als lokale Eingaben – wie in der App getippt. Im Chat stehen sie als „Lokale API“.
export THERON=http://127.0.0.1:8767/v1 THERON_TOKEN=… curl -H "Authorization: Bearer $THERON_TOKEN" $THERON/status
Endpunkte
| Methode & Pfad | Was passiert |
|---|---|
GET /status | Version und ID des neuesten Ereignisses. |
GET /processes | Prozesse (ID, Name, Schritte) – für process_id. |
GET /projectsPOST /projects | Projekte auflisten / anlegen:
{name, description?, rules?, workspace?, process_id?}. workspace ist ein absoluter
Pfad und wird bei Bedarf angelegt. |
GET /projects/{id}PATCH /projects/{id} | Lesen / einzelne Felder ändern. |
GET /projects/{id}/tasks | Die Tasks des Projekts, neueste zuerst. |
POST /projects/{id}/tasks | Task starten: {text, title?} – oder
{tasklist_id}, um eine Task-Liste abzuarbeiten. Braucht einen Prozess mit mindestens einem Schritt. |
GET /tasks/{id}?events=50 | Status (running, waiting_input,
done, failed, stopped), summary, goal_reached,
die offene Rückfrage in pending_input und auf Wunsch die letzten Ereignisse. |
POST /tasks/{id}/messages | Nachricht an Theron: {text}. |
POST /tasks/{id}/answer | Offene Rückfrage beantworten: {text, request_id?}
(eine der pending_input.options oder freier Text). |
POST /tasks/{id}/stop | Stoppen – {"soon": true} lässt laufende Schritte
erst fertig werden. |
GET /projects/{id}/tasklists | Task-Listen mit Fortschritt. |
POST /projects/{id}/tasklists | Task-Liste anlegen, auf Wunsch gleich mit Epics und Requirements (siehe unten). |
GET /tasklists/{id}PATCH · DELETE | Die ganze Liste: Epics in Ausführungsreihenfolge mit ihren Requirements, Status, Ergebnis und Protokoll. |
POST /tasklists/{id}/epics | Epic hinzufügen: {name, description?, depends_on?,
requirements?}. |
POST /tasklists/{id}/start | Task starten, der die Liste abarbeitet. |
GET /epics/{id}PATCH · DELETE | Epic: name,
description, depends_on, closed. |
POST /epics/{id}/requirements | Requirement hinzufügen: {title, description?,
acceptance?, tech_rules?, depends_on?}. |
GET /requirements/{id}PATCH · DELETE | Requirement –
status: open, in_progress, hitl, done, failed, skipped, closed; dazu
result. |
GET /events | Ereignisse per Long-Polling – siehe unten. |
Alle Pfade beginnen mit /v1. depends_on ist eine Liste von Epic- bzw.
Requirement-IDs, die vorher erledigt sein müssen.
Befüllte Task-Liste anlegen
curl -X POST $THERON/projects/3/tasklists -H "Authorization: Bearer $THERON_TOKEN" \
-H "Content-Type: application/json" -d '{
"name": "Sprint 12",
"epics": [{"name": "Checkout", "requirements": [
{"title": "Mit PayPal bezahlen", "acceptance": "Zahlung gebucht, Bestellung bestätigt"},
{"title": "Rechnung als PDF"}]}]}'
Ereignisse
GET /events?since=<id>&wait=30 liefert die Ereignisse nach since (älteste
zuerst) und next – das gibst du beim nächsten Aufruf als since mit. Mit wait
(max. 60 s) wartet die Anfrage, bis etwas passiert. since=-1 beginnt bei allem, was ab jetzt passiert.
Filter: project, task, types=a,b.
| Typ | Bedeutung |
|---|---|
status | Status des Tasks geändert (status, phase). |
input_request | Theron fragt: request_id, question, options, recommended. |
input_resolved | Eine Rückfrage wurde beantwortet. |
complete | Task abgeschlossen: summary, goal_reached. |
requirement_start · requirement_status · requirement_done |
Fortschritt der Task-Liste, mit requirement_id (und success am Ende). |
alert | ⚑ Meldung aus dem Prozess (level, text, stop). |
orchestrator · user | Chat-Nachrichten. |
agent_start · agent_end · handover | Schritte der Agents. |
Beispiel: Synchronisation mit Trello (Python)
Karten einer Trello-Liste werden zu Requirements; ist eines erledigt, wandert die Karte nach „Done“. Es reicht die Standardbibliothek; die Trello-Aufrufe sind als Funktionen zum Ausfüllen gelassen.
import json, os, urllib.request
API, TOKEN = "http://127.0.0.1:8767/v1", os.environ["THERON_TOKEN"]
def theron(method, path, body=None):
req = urllib.request.Request(API + path, method=method, data=json.dumps(body).encode() if body else None,
headers={"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=90) as r:
return json.load(r)
cards = trello_cards("To do") # dein Trello-Aufruf: [{"id", "name", "desc"}, …]
tl = theron("POST", "/projects/3/tasklists", {"name": "Trello", "epics": [{"name": "Board", "requirements": [
{"title": c["name"], "description": c["desc"]} for c in cards]}]})
card_of = {r["id"]: c["id"] for c, r in zip(cards, tl["epics"][0]["requirements"])} # gleiche Reihenfolge
task = theron("POST", f"/tasklists/{tl['id']}/start", {})
since = theron("GET", "/status")["last_event"]
while True:
page = theron("GET", f"/events?since={since}&wait=60&task={task['id']}")
since = page["next"]
for ev in page["events"]:
if ev["type"] == "requirement_done" and ev["success"]:
trello_move(card_of[ev["requirement_id"]], "Done")
elif ev["type"] == "input_request":
print("Theron fragt:", ev["question"], ev["options"]) # Antwort: POST /tasks/{id}/answer
elif ev["type"] == "complete":
raise SystemExit(ev["summary"])