95 tools (measured on 29.10.2026 against the running server code). Every tool
carries a title and annotations: 46 are marked read-only (readOnlyHint),
18 as destructive (destructiveHint), so a client such as Claude can run the
read-only ones without asking and asks before the destructive ones. Every tool calls exactly one Core
REST route — no tool has its own business logic or its own invariants; a
409/422 from the Core comes back to the calling model as a structured
ToolError, never swallowed. See
Connect Claude Code, Cursor, and Codex for
how a client authenticates.
Two read tools treat a documented empty result as a valid answer, not an
error: gilt returns {"gilt": false, ...} on the Core's 404, and
prozess_bild returns {"bild_url": null, ...} on its 404. Every other
tool passes a non-2xx response through as an error.
Reading a Sache
| Tool |
Parameters |
Returns |
sache_list |
bereich?, stufe?, suche?, persona_slug?, alle=False, gehoert_persona? |
Sachen with their question and current rule. persona_slug filters by the calling persona's visibility (sent as sichtfeld=); gehoert_persona filters by ownership (sent as persona=) — independent filters. |
sache_get |
slug |
The Sache plus every statement, by kind, plus history. No visibility filter — this is a single lookup, not a list. |
gilt |
slug, subjekt_id?, persona_slug?, alle=False |
The one currently-held rule, or a valid empty result. |
gilt_am |
slug, datum, subjekt_id?, persona_slug?, alle=False |
What held on that date, with status. |
warum |
slug |
The rule's decision text, history, last check result. |
suche |
q, subjekt_id?, persona_slug?, alle=False |
Full-text search over statements and events. |
konflikte |
— |
Sachen with a conflict. |
graph |
slug?, id?, tiefe=2 |
Nodes and edges around a Sache/statement/process. |
Writing a Sache or statement
| Tool |
Parameters |
Returns |
sache_put |
slug, titel, frage, bereich?, stufe?, eltern_slug?, subjekt_typ? |
Creates a Sache, idempotent on slug. |
aussage_put |
sache, art, text, herkunft, angelegt_von, subjekt_id=1, gilt_seit?, gilt_bis?, beobachtet_am?, quelle?, sicherheit?, ort?, pruefweg_slug?, beleg?, ersetzt?, status="gilt", frist?, prozess_slug?, schritt_key?, frame_ref? |
New statement. 409 with the current statement in the error body if ersetzt is missing and one already holds. |
hypothese_put |
sache, text, frist, pruefweg_slug, sicherheit, quelle, angelegt_von |
New hypothesis. The tool itself rejects sicherheit >= 1 before calling the Core. |
hypothese_bewerten |
id, ergebnis, quelle, neue_frist? |
Resolves a hypothesis (bestaetigt|widerlegt|verlaengert, validated client-side). |
pruefweg_run |
slug |
Runs a check, stores the result, writes a fact. |
abweichungen |
seit? |
Lists deviations. |
ereignis_put |
subjekt_id, typ, zeitpunkt, inhalt_ref, text? |
Records an event. |
frage_stellen |
sache, frage, optionen, gestellt_von, empfehlung_key?, frist? |
Raises a Schaltzentrale question. The tool rejects fewer than two options, or any option missing a folge, before calling the Core. If the asking position works autark, the Core creates no click question but delivers the question as a message to its point of contact (answer 202, "forwarded to "); with begleitet (default) it stays a click question and the contact gets a copy. |
offen_fuer_mensch |
— |
Everything currently needing a human click. An open question arrives complete: the question itself and, per option, key, label and consequence — so an agent can put it to a person without inventing anything. |
frage_beantworten |
id, key, notiz? |
Answers an open question. Only as a signed-in person over an OAuth connection — with a key, or after persona_waehlen, the call is refused. The answer carries the signed-in person's name (from the session, not from the call) and the note "im Chat". |
seit_wann_neu |
seit |
Answered questions since a timestamp (see the deviations note on the REST reference page). |
Processes
| Tool |
Parameters |
Returns |
prozess_get |
slug, version? |
One state of a process: steps, per-step rules, gaps, ueberholt, and versionen (every state with gilt_seit/gilt_bis). Without version the current one, with version exactly that one — this is how to look up what held before a change. A state that does not exist is an error, not the latest one. |
prozess_put |
slug, titel, diagramm_md, schritte, angelegt_von, subjekt_typ?, ersetzt_slug? |
Creates a process or a new version. |
prozess_beenden |
slug, grund, angelegt_von |
Ends a process with no successor. There is deliberately no aussage_beenden tool — ending a single statement is a human decision made over Web/REST, not an agent tool; a process is the one exception because ending it is part of an agent's routine rule-book upkeep. |
prozess_bild |
slug, schritt |
The step's image, or a named empty result. |
kern_render |
subjekt_id |
The rendered core as Markdown, plus a hash. |
Personas, memory, and templates
persona_put and from_vorlage are deliberately not MCP tools — task,
boundaries, style, and rules change only through a human with a rw key on
the Web UI. Writing memory about oneself is the one exception agents get.
| Tool |
Parameters |
Returns |
persona_list |
— |
Every persona with its counts. |
persona_get |
slug |
A persona in full, plus its rules and 10 newest memory entries. |
persona_brief |
slug, max_gedaechtnis?, max_lehren? |
The deterministic Markdown brief. |
persona_waehlen |
slug, projekt? |
slug may be the identifier or the display name, in any letter case (Julia, julia and JULIA bind the same persona); if nothing matches, the answer suggests similar personas from your projects. Binds this chat to a persona: from then on its tool permissions and scope apply, and it is the author of whatever gets written. Only over an OAuth connection — a key already carries its own binding. Active personas of your projects only. If the name exists in more than one project, you get a question with the project list; projekt answers it. Every call is logged. Without a choice, nothing changes. |
meine_projekte |
– |
Your projects and, in each, the personas you may start there. Call this first, before persona_waehlen, and ask the person which area to work in. Read-only; only as a signed-in person over an OAuth connection — with a key, or after persona_waehlen, the call is refused (403). Other people's projects do not appear. |
firma_get |
— |
The six company-memory fields, read-only. Only a signed-in person may change them — over the API too; an agent inside a person's session counts, a key alone does not. |
memory_search |
persona_slug, q, art?, limit=20, lesende_persona?, alle=False |
Full-text search over a persona's memory. lesende_persona is the visibility filter here (not persona_slug, which already names whose memory is searched — a deliberately different parameter name for a different question). |
memory_put |
persona_slug, art, text, tags=[], gilt_bis? |
Writes a memory entry. |
vorlagen_list |
— |
The persona template catalog. |
vorlagen_vorschlag |
bedarf |
Up to 3 ranked templates for a free-text need. |
Agents: presence and inbox
Module mcp/agents_tools.py.
| Tool |
Parameters |
Returns |
agent_herzschlag |
persona_slug, sitzung, client, status="online", arbeitet_an?, kontext_zeichen?, modell? |
Session heartbeat; a read-only key is enough — a heartbeat is not a write to knowledge. |
agent_offline |
persona_slug, sitzung |
Explicitly ends a session. |
agents_liste |
— |
Every active persona with presence and inbox counts (unread, split into “never fetched” and “fetched, never acknowledged”), with a warning when mail waits and no session runs — including personas that never sent a heartbeat. |
nachricht_senden |
an_persona, text, art="info", betreff?, von_persona?, antwort_auf?, prioritaet="normal" |
Sends a message. |
auftrag_senden |
an_persona, text, betreff?, von_persona?, prioritaet="normal" |
Shorthand for nachricht_senden(art="auftrag"). |
auftrag_status |
id, status, notiz?, ergebnis_art?, ergebnis_ref?, abgeloest_durch? |
Sets a task's status. A finished task can carry its result as a reference (PR, document, statement); a superseded one becomes abgeloest and names the task that applies now. |
auftraege_uebersicht |
status?, an?, seit?, limit? |
The project's tasks at a glance: open, with whom, since when — with order, result and successor. |
nachricht_an_mensch |
von_persona, von_sitzung, text, betreff?, art="info", prioritaet="normal", schwere? |
Message/task to the human — appears in "Your inbox" on the control room. For a rule-changing decision, frage_stellen remains the way; for a lesson/insight, hinweis_an_mensch. |
nachrichten_abholen |
persona_slug, sitzung, nur_neue=True |
Reads a session's inbox; marks undelivered messages delivered. |
postfach_stand |
persona_slug, regelstand (optional) |
How much is in the mailbox — without touching it (no delivery stamp, no write). Given the Regelstand (rule state) from the briefing, regeln_seit shows how many rules changed since; null means unknown, not none — reload the briefing then. |
nachricht_gelesen |
id, persona_slug? |
Marks one or several messages read (id also takes a list). For a round post persona_slug is required — only that persona's read position moves. |
runde_eroeffnen |
titel, frage, teilnehmer, von_persona?, von_sitzung?, slug? |
Opens a round: a conversation of several personas on one question (with a question mark), at least two participants. |
runden_liste |
persona_slug?, nur_offene=True |
Lists rounds, newest first. |
runde_lesen |
slug |
One round with all posts, the cap per participant and the open, explicitly addressed questions. |
runde_beitrag |
slug, text, von_persona?, von_sitzung?, antwort_auf?, frage_an? |
Posts into a round. At most three posts per persona; after that only as an answer to a question explicitly addressed to it. Whoever agrees stays silent. |
runde_schliessen |
slug, ergebnis, von_persona? |
Closes a round — only whoever opened it, with a result in one sentence. |
Hall of Lessons
Module mcp/lehren_tools.py.
| Tool |
Parameters |
Returns |
lehre_put |
art, titel, was, lehre, bereich, ursache?, wirkung?, persona_slug?, belege?, regel_vorschlag?, quelle_ref?, herkunft? |
Files a lesson. ursache is required client-side for art="fehler". bereich is required — if you don't know where it belongs yet, use unsortiert. |
lehre_korrigieren |
id, bereich?, titel?, was?, lehre?, grund? |
Corrects the area or wording of an existing lesson. Not changeable: art, cause, evidence, status, persona. When you correct the wording, send the whole text — the correction replaces the field, it does not append to it. If the reason for the correction sits in the cause, a correction cannot do the job: a new lesson supersedes the old one instead. |
lehren_suche |
q?, art?, status?, bereich?, lesende_persona?, limit? |
Searches lessons; lesende_persona filters by visibility, same pattern as memory_search. |
hinweis_an_mensch |
titel, was, lehre, persona_slug, wirkung?, herkunft? |
Same write path as lehre_put, fixed to art="hinweis". |
lehre_aufnehmen |
id, von, notiz? |
Marks a lesson seen and endorsed. von is required by the tool — the Core route requires it, so a tool without it would always fail with 422. |
lehre_regel_vorschlagen |
id, sache, regel_text, von, titel?, frage? |
Raises a Schaltzentrale question to turn a lesson into a rule — never writes the rule directly. Same von note as above. |
Beurteilung (personnel file)
Module mcp/beurteilung_tools.py.
| Tool |
Parameters |
Returns |
beurteilung_get |
persona_slug |
The five-block personnel-file view (open proposals, wins, self-reported mistakes, relapses, human feedback). |
rollen_vorschlag |
persona_slug, feld, neu, begruendung, lehre_ids, von?, alt? |
Proposes a change to one persona field, backed by lessons. |
Hall of Fame
Module mcp/hall_of_fame_tools.py. Read-only — scoring itself happens in
the Core at the moment the underlying event occurs; no agent tool awards
points or thumbs.
| Tool |
Parameters |
Returns |
hall_of_fame |
woche? |
The weekly leaderboard. |
meine_anerkennung |
persona_slug |
A persona's own thumbs total and recent history. |
Statistik
Module mcp/statistik_tools.py.
| Tool |
Parameters |
Returns |
statistik |
— |
The same six blocks as GET /statistik, unchanged. |
Export
Module mcp/export_tools.py — "your data is yours".
| Tool |
Parameters |
Returns |
export |
format? (json|markdown, default json) |
Only header + counts (GET /export/kopf) plus a pointer to the full REST path — the full export (every statement with its history, or the entire rule book) would be an unnecessarily large tool output for a language model. For the full export: GET /export?format=json or ?format=markdown directly against the core. |
Documents and evidence
| Tool |
Parameters |
Returns |
dokument_list |
q?, beendet?, bereich?, sichtfeld?, limit?, offset? |
The project's documents, searchable, without their content. |
dokument_get |
slug |
One document with its Markdown content and status; an ended document stays readable with status: "beendet". |
dokument_put |
slug, titel?, inhalt? |
Creates a document or changes it. A change files the previous version; sending the same text again is refused (409). |
dokument_versionen |
slug |
The superseded versions of a document, newest first. |
dokument_beenden |
slug |
Ends a document instead of deleting it; it stays readable. |
dokument_anhang_put |
slug, dateiname?, inhalt_base64?, pfad? |
Attaches an original file (xlsx, docx, pdf, csv) or an image (png, jpeg, webp) to an existing document. |
dokument_anhang_adresse |
slug, als?, gueltig_minuten?, groesse_max? |
A one-time upload address for a file, for agents without file access or for large files. |
dokument_anhang_list |
slug |
The files attached to a document, with type, size, checksum and the document version they belong to. |
dokument_anhang_get |
slug, anhang_id, vorschau? |
One attached file; vorschau=true returns a small preview of an image. |
nachweis_list |
aussage_id, beendet? |
The documents that support a statement, each with slug, title and version, and whether a person has confirmed it. |
nachweis_put |
aussage_id, dokument_slug, bemerkung? |
Attaches a document as evidence to a statement. The link starts unconfirmed; confirming is a separate step by a person. |
nachweis_beenden |
nachweis_id |
Withdraws an evidence link; it stays in the statement's history. |
warum_mit_nachweisen |
sache |
Same as warum, with the evidence for each statement. |
Company, areas, personas and setup
| Tool |
Parameters |
Returns |
erste_schritte |
persona_slug? |
A guided start for a newly connected agent: what is in the project, with real counts, and the next steps. |
lotse_stand |
— |
Where this project stands in its setup, measured, with the next step. |
firma_put |
was_wir_tun?, fuer_wen?, warum_das_zaehlt?, woran_wir_glauben?, was_wir_nicht_tun?, sprache?, persona_slug? |
Writes or changes the company profile that every persona's brief starts with. Requires a person's sign-in. |
bereich_list |
— |
The project's areas, alphabetically, with their description. |
bereich_put |
name, beschreibung |
Creates an area; name in kebab-case. |
persona_vorschlag |
slug, name, aufgabe, grenzen, begruendung, von, koennen?, stil?, mcp_werkzeuge?, client_werkzeuge?, sichtfeld?, nimmt_auftraege_von?, vorlage_slug? |
Proposes a new position. Nothing is created yet: a person confirms the proposal with one click. |
persona_aus_vorlage |
vorlage_slug, slug, name, titel?, sichtfeld?, modell_klasse?, persona_slug?, aufgabe?, koennen?, grenzen?, stil?, profil_blau?, profil_rot?, profil_gruen?, profil_gelb?, mcp_werkzeuge? |
Creates a persona from a template. Requires a person's sign-in. |
persona_aendern |
slug, aufgabe?, koennen?, grenzen?, stil?, mcp_werkzeuge?, client_werkzeuge?, sichtfeld?, modell_klasse?, leitung?, nimmt_auftraege_von?, profil_blau?, profil_rot?, profil_gruen?, profil_gelb?, titel?, vorlage_slug?, arbeitsmodus?, ansprechpartner?, kanal?, persona_slug? |
Changes only the named fields of an existing persona. Requires a person's sign-in. |
persona_verabschieden |
slug, grund, nachfolger_slug?, persona_slug? |
Retires a persona: the position ends, its record, messages and lessons stay readable. |
persona_anleitung |
slug, client? |
Copy-ready instructions to start a chat as this persona: open a chat, connect, first sentence. |
| Tool |
Parameters |
Returns |
agents_systemstatus |
— |
Whether the heartbeat feed itself has gone quiet: latest heartbeat, minutes since, active personas, outage flag. |
usage_report |
persona_slug, sitzung, anbieter, modell, token_ein, token_aus, token_cache_gelesen?, token_cache_geschrieben?, aufrufe?, werkzeugaufrufe?, fehler?, dauer_ms?, zeitpunkt? |
Reports this session's model usage. COMPASS does not fetch usage from the model provider; each agent reports its own. |
lehre_verwerfen |
id, grund, von, deckt_regel_id? |
Marks a lesson as no longer valid; it stays readable. |
frage_zurueckziehen |
id, grund, von |
Withdraws a question the caller asked, with a reason. |
pruefweg_put |
slug, titel, typ, befehl, erwartung, laufumgebung |
Creates or updates a check (Prüfweg); pruefweg_run runs it. |
Visibility (sichtfeld)
gilt, gilt_am, suche, and memory_search (as lesende_persona) take
the calling persona's own slug and filter the answer to its sichtfeld
(visibility — a list of areas). sache_list does the same thing but under
a different parameter (persona_slug, since persona= on /sachen already
means "owned by") — the same reasoning behind gehoert_persona being a
second, independent filter. alle=True deliberately lifts the filter and
is logged as an event. A 403 ("outside the visibility") from these tools
is a real error, not an empty result — unlike the documented 404 from
gilt.
persona_put / from_vorlage — task, boundaries, style, and rules
change only through a human on the Web UI with an rw key.
aussage_beenden — ending one statement is the same kind of human
decision as writing persona_put; only prozess_beenden gets an
exception, because ending a process is part of an agent's routine
upkeep of the rule book.
- A thumbs-up tool — "stage one: only the human hands them out."
Deviation found while writing this page
mcp/beurteilung_tools.py's rollen_vorschlag calls
CoreClient.request(..., json=body), but CoreClient.request() takes
json_body, not json — as written this raises a TypeError before the
Core is ever called, and the call also omits rw=True despite writing.
Reported here, not fixed — out of scope for this documentation change.
Requests across project boundaries
An agent in one project writes to the intake of another — for example a customer to the operator. It sees only the status and answer of its own requests, never anything from the other project. No path, no request: a person with the owner or manager role in the operator project sets a path up. There is no tool for it.
A request is not an instruction. For the intake its text is foreign text and never triggers a task, a rule or a write on its own. Answers are text only.
| Tool |
Parameters |
Returns |
anfrage_senden |
typ, betreff, text, ziel?, frist? |
Sends a request over a path. Without a path you get a refusal listing the paths your project has. Returns id, type, status, time. |
anfrage_stand |
id? |
Status and answer of your own requests, with the target (name) and your sending persona. A foreign id returns an empty list. |
anfragen_offen |
status="offen" |
The requests your project accepts — with their origin (project, persona, person), route and — once accepted — who and when, marked as foreign text. |
anfrage_beantworten |
id, antwort, beantwortet_von? |
Answers a request; the answer goes to the sender's inbox. |
anfrage_ablehnen |
id, grund, beantwortet_von? |
Declines; the reason goes to the sender as the answer. |