TaskMonkey Handbuch

Agent-Delegation (invoke_assistant / spawn_agent)

Master-Assistants delegieren an bestehende Assistants oder bauen Ad-hoc-Agenten on the fly. Sub-Chats via parent_chat_id verlinkt.

Ein Master-Assistant kann Teilaufgaben an andere Assistants delegieren oder Ad-hoc-Agenten mit selbst gewähltem Prompt + Tools bauen. Die Sub-Chats laufen unter eigener chat_id, sind via parent_chat_id + parent_message_id auf den Master verlinkt, und liefern ihre finale Reply als Tool-Result zurück.

Dahinter stehen zwei globale Tools, die in _shared/tools/ registriert sind. Nur bewusst freischalten — nicht in Public-Chat-Assistants aufnehmen.

Zwei Muster

Tool Wann
invoke_assistant Es gibt bereits einen konfigurierten Assistant, der für die Teilaufgabe passt. Slug reicht — Prompt + Tools kommen aus dessen Config.
spawn_agent Kein bestehender Assistant passt. Master gibt Prompt + Tool-Liste zur Laufzeit mit. Optional based_on: <slug> als Ausgangspunkt.

Beide sind wegwerf-orientiert aus Master-Sicht: der Master sieht nur die finale Reply des Sub-Chats, kein Zwischen-Tool-Reasoning.

Config

Master-Assistant (z. B. agent_proto) bekommt die beiden Tools freigeschaltet:

'tools' => [
    'invoke_assistant',
    'spawn_agent',
    // ... andere Tools des Masters
],

An allen anderen Assistants ändert sich nichts. Sie sind ohne weiteres Zutun via invoke_assistant("slug", ...) aus dem Master aufrufbar — der Slug ist ihr Config-Key.

Public-Chat-Assistants (public.tools) dürfen die zwei Tools nicht haben. Es gibt keinen zentralen Schutz — die Regel ist eine Convention: nicht in public.tools aufnehmen.

Aufrufe

invoke_assistant:

{
  "assistant": "retoure",
  "task": "Kunde will Bestellung 12345 zurücksenden, was ist der Status?",
  "context": "Kunde hat vor 3 Wochen bestellt, ohne Retour-Label."
}

spawn_agent:

{
  "task": "Fasse die letzten 5 Reklamationen in 3 Sätzen zusammen.",
  "prompt": "Du bist ein knapper Report-Bot. Antworte in Bullet-Points.",
  "tools": ["getSalesOrdersSince", "runPython"],
  "based_on": "kpi",
  "context": "Zeitraum: letzte 7 Tage."
}

context ist optional und wird an den System-Prompt des Sub-Chats gehängt. Der Master entscheidet aktiv, welche Fakten aus seinem Verlauf der Sub sehen soll — der Sub-Chat sieht sonst nichts vom Master-Verlauf.

Sub-Chat-Anatomie

  • Eigene chat_id im Format sub_<parent-chat-id>_<8-hex> — sortierbar, Parent auf einen Blick erkennbar
  • Eigener chat_threads-Row mit:
    • parent_chat_id (Master-chat_id)
    • parent_message_id (chat_messages.id des auslösenden Tool-Calls, UUID; NULL wenn kein Parent-Message-Verweis)
  • Eigene chat_messages-Rows (system, user, assistant, ggf. tool)

Der Sub-Chat ist eigenständig wiederherstellbar — bei Bedarf kann der User ihn als eigenen Chat fortführen.

Recursion-Guard

Maximaler Delegations-Baum: Tiefe 2. Master → Sub → Sub-Sub darf noch, Master → Sub → Sub-Sub → weiter nicht. SubChatRunner::currentDepth folgt den parent_chat_id-Hops und bricht ab.

Provider- und Tool-Auflösung

  • AiProviderFactory::forChat wird für den Sub-Chat mit dessen assistantConfig gerufen — d. h. ein Sub-Assistant mit eigenem llm-Profil bekommt sein eigenes LLM/Modell, sonst fällt es auf den Tenant-Default zurück.
  • Ein eigener ToolRunner wird gestartet, mit einer setAllowedTools()-Whitelist aus der tools-Liste des Sub-Assistants (bzw. dem tools-Argument bei spawn_agent).
  • Der Master kann bei spawn_agent nur Tools freischalten, die er selbst kennt — die Whitelist basiert auf dem Argument, nicht auf einer eigenen Master-Freigabe. Wer die Tools missbraucht, ist der Master (der eh Vollzugriff hat).

Sichtbarkeit für den Master

Der Master sieht als Tool-Result:

{
  "success": true,
  "sub_chat_id": "sub_abc123_4a1f",
  "reply": "…finale Reply des Sub-Assistants…",
  "tools_used": ["getPricingBySku"],
  "iterations": 1,
  "error": null
}

Das reicht, damit er entscheidet, wie er die Antwort in seine Response weiterverwebt. Der Sub-Chat ist per sub_chat_id referenzierbar (Preview-Card im Frontend, folgt separat).

Tests

# invoke_assistant CLI-Test
bin/cake test_tool --tenant bloomify --tool invoke_assistant \
  --args='{"assistant":"preise","task":"Was kostet SKU B12345?"}'

# spawn_agent CLI-Test
bin/cake test_tool --tenant bloomify --tool spawn_agent \
  --args='{"task":"Sag Hallo","prompt":"Antworte mit einem Satz.","tools":[]}'

chat_threads-Row per SQL prüfen:

SELECT chat_id, parent_chat_id, parent_message_id, status
FROM chat_threads
WHERE tenant='bloomify' AND parent_chat_id IS NOT NULL
ORDER BY id DESC LIMIT 5;

Verwandte Doks

Zuletzt aktualisiert: 2026-07-28