Session-Tools

Ziel: kleines, schwer missbrauchbares Tool-Set, mit dem Agents Sessions auflisten, Historie abrufen und Nachrichten an andere Sessions senden koennen.

Tool-Namen

  • sessions_list
  • sessions_history
  • sessions_send
  • sessions_spawn

Key-Modell

  • Der Haupt-Direktchat-Bucket ist immer der literale Key "main" (wird auf den Main-Key des aktuellen Agents aufgeloest).
  • Gruppenchats nutzen agent:<agentId>:<channel>:group:<id> oder agent:<agentId>:<channel>:channel:<id> (den vollstaendigen Key uebergeben).
  • Cron-Jobs nutzen cron:<job.id>.
  • Hooks nutzen hook:<uuid>, sofern nicht explizit gesetzt.
  • Node-Sessions nutzen node-<nodeId>, sofern nicht explizit gesetzt.

global und unknown sind reservierte Werte und werden nie aufgelistet. Wenn session.scope = "global", wird es fuer alle Tools zu main aliased, damit Aufrufer nie global sehen.

sessions_list

Sessions als Array von Zeilen auflisten.

Parameter:

  • kinds?: string[] Filter: beliebige aus "main" | "group" | "cron" | "hook" | "node" | "other"
  • limit?: number max. Zeilen (Standard: Server-Standard, z.B. 200 gedeckelt)
  • activeMinutes?: number nur Sessions, die innerhalb von N Minuten aktualisiert wurden
  • messageLimit?: number 0 = keine Nachrichten (Standard 0); >0 = letzte N Nachrichten einschliessen

Verhalten:

  • messageLimit > 0 ruft chat.history pro Session ab und schliesst die letzten N Nachrichten ein.
  • Tool-Ergebnisse werden in der Listenausgabe herausgefiltert; verwende sessions_history fuer Tool-Nachrichten.
  • In einer sandboxed Agent-Session verwenden Session-Tools standardmaessig Spawned-only-Sichtbarkeit (siehe unten).

Zeilenformat (JSON):

  • key: Session-Key (String)
  • kind: main | group | cron | hook | node | other
  • channel: whatsapp | telegram | discord | signal | imessage | webchat | internal | unknown
  • displayName (Gruppen-Anzeigelabel, falls verfuegbar)
  • updatedAt (ms)
  • sessionId
  • model, contextTokens, totalTokens
  • thinkingLevel, verboseLevel, systemSent, abortedLastRun
  • sendPolicy (Session-Override, falls gesetzt)
  • lastChannel, lastTo
  • deliveryContext (normalisiert { channel, to, accountId }, wenn verfuegbar)
  • transcriptPath (Best-Effort-Pfad, abgeleitet aus Store-Dir + sessionId)
  • messages? (nur wenn messageLimit > 0)

sessions_history

Transkript fuer eine Session abrufen.

Parameter:

  • sessionKey (erforderlich; akzeptiert Session-Key oder sessionId aus sessions_list)
  • limit?: number max. Nachrichten (Server-seitig gedeckelt)
  • includeTools?: boolean (Standard false)

Verhalten:

  • includeTools=false filtert role: "toolResult"-Nachrichten heraus.
  • Gibt das Nachrichten-Array im Roh-Transkript-Format zurueck.
  • Bei Angabe einer sessionId loest OpenClaw sie zum entsprechenden Session-Key auf (fehlende IDs fuehren zu einem Fehler).

sessions_send

Nachricht in eine andere Session senden.

Parameter:

  • sessionKey (erforderlich; akzeptiert Session-Key oder sessionId aus sessions_list)
  • message (erforderlich)
  • timeoutSeconds?: number (Standard >0; 0 = Fire-and-Forget)

Verhalten:

  • timeoutSeconds = 0: einreihen und { runId, status: "accepted" } zurueckgeben.
  • timeoutSeconds > 0: bis zu N Sekunden auf Abschluss warten, dann { runId, status: "ok", reply } zurueckgeben.
  • Bei Timeout: { runId, status: "timeout", error }. Der Lauf geht weiter; spaeter sessions_history aufrufen.
  • Bei Fehler: { runId, status: "error", error }.
  • Announce-Delivery-Laeufe finden nach dem primaeren Lauf statt und sind Best-Effort; status: "ok" garantiert nicht, dass die Announce-Nachricht zugestellt wurde.
  • Warten per Gateway agent.wait (Server-seitig), sodass Reconnects das Warten nicht unterbrechen.
  • Agent-zu-Agent-Nachrichtenkontext wird fuer den primaeren Lauf injiziert.
  • Inter-Session-Nachrichten werden mit message.provenance.kind = "inter_session" persistiert, damit Transkript-Leser geroutete Agent-Anweisungen von externen Nutzereingaben unterscheiden koennen.
  • Nach Abschluss des primaeren Laufs fuehrt OpenClaw eine Reply-Back-Schleife aus:
    • Ab Runde 2 wechseln Requester- und Ziel-Agent sich ab.
    • Antworte mit genau REPLY_SKIP, um das Ping-Pong zu stoppen.
    • Maximale Runden: session.agentToAgent.maxPingPongTurns (0-5, Standard 5).
  • Nach Ende der Schleife fuehrt OpenClaw den Agent-zu-Agent-Announce-Schritt aus (nur Ziel-Agent):
    • Antworte mit genau ANNOUNCE_SKIP, um still zu bleiben.
    • Jede andere Antwort wird an den Zielkanal gesendet.
    • Der Announce-Schritt enthaelt den urspruenglichen Request + Runde-1-Antwort + letzte Ping-Pong-Antwort.

Channel-Feld

  • Fuer Gruppen ist channel der auf dem Session-Eintrag aufgezeichnete Kanal.
  • Fuer Direktchats wird channel aus lastChannel abgeleitet.
  • Fuer Cron/Hook/Node ist channel internal.
  • Falls fehlend, ist channel unknown.

Sicherheit / Send Policy

Richtlinienbasierte Blockierung nach Kanal/Chat-Typ (nicht pro Session-ID).

{
  "session": {
    "sendPolicy": {
      "rules": [
        {
          "match": { "channel": "discord", "chatType": "group" },
          "action": "deny"
        }
      ],
      "default": "allow"
    }
  }
}

Runtime-Override (pro Session-Eintrag):

  • sendPolicy: "allow" | "deny" (nicht gesetzt = Config erben)
  • Setzbar per sessions.patch oder Owner-only /send on|off|inherit (eigenstaendige Nachricht).

Enforcement-Punkte:

  • chat.send / agent (Gateway)
  • Auto-Reply-Delivery-Logik

sessions_spawn

Sub-Agent-Lauf in einer isolierten Session starten und das Ergebnis im Requester-Chat-Kanal ankuendigen.

Parameter:

  • task (erforderlich)
  • label? (optional; fuer Logs/UI)
  • agentId? (optional; unter einer anderen Agent-ID spawnen, falls erlaubt)
  • model? (optional; ueberschreibt das Sub-Agent-Modell; ungueltige Werte fuehren zu einem Fehler)
  • thinking? (optional; ueberschreibt das Thinking-Level fuer den Sub-Agent-Lauf)
  • runTimeoutSeconds? (Standard: agents.defaults.subagents.runTimeoutSeconds falls gesetzt, sonst 0; bricht den Sub-Agent-Lauf nach N Sekunden ab)
  • thread? (Standard false; thread-gebundenes Routing fuer diesen Spawn anfordern, wenn vom Kanal/Plugin unterstuetzt)
  • mode? (run|session; Standard run, aber Standard session wenn thread=true; mode="session" erfordert thread=true)
  • cleanup? (delete|keep, Standard keep)
  • sandbox? (inherit|require, Standard inherit; require lehnt Spawn ab, wenn die Ziel-Child-Runtime nicht sandboxed ist)
  • attachments? (optionales Array von Inline-Dateien; nur Subagent-Runtime, ACP lehnt ab). Jeder Eintrag: { name, content, encoding?: "utf8" | "base64", mimeType? }. Dateien werden im Child-Workspace unter .openclaw/attachments/<uuid>/ materialisiert. Gibt eine Quittung mit sha256 pro Datei zurueck.
  • attachAs? (optional; { mountPath? } Hinweis, reserviert fuer zukuenftige Mount-Implementierungen)

Allowlist:

  • agents.list[].subagents.allowAgents: Liste erlaubter Agent-IDs per agentId (["*"] fuer beliebige). Standard: nur der anfragende Agent.
  • Sandbox-Inheritance-Guard: Wenn die Requester-Session sandboxed ist, lehnt sessions_spawn Ziele ab, die unsandboxed laufen wuerden.

Discovery:

  • Nutze agents_list, um herauszufinden, welche Agent-IDs fuer sessions_spawn erlaubt sind.

Verhalten:

  • Startet eine neue agent:<agentId>:subagent:<uuid>-Session mit deliver: false.
  • Sub-Agents nutzen standardmaessig das volle Tool-Set ohne Session-Tools (konfigurierbar ueber tools.subagents.tools).
  • Sub-Agents duerfen sessions_spawn nicht aufrufen (kein Sub-Agent -> Sub-Agent-Spawning).
  • Immer non-blocking: gibt sofort { status: "accepted", runId, childSessionKey } zurueck.
  • Mit thread=true koennen Kanal-Plugins Delivery/Routing an ein Thread-Ziel binden (Discord-Unterstuetzung wird ueber session.threadBindings.* und channels.discord.threadBindings.* gesteuert).
  • Nach Abschluss fuehrt OpenClaw einen Sub-Agent-Announce-Schritt aus und postet das Ergebnis im Requester-Chat-Kanal.
    • Wenn die finale Assistant-Antwort leer ist, wird das letzte toolResult aus der Sub-Agent-Historie als Result eingeschlossen.
  • Antworte mit genau ANNOUNCE_SKIP im Announce-Schritt, um still zu bleiben.
  • Announce-Antworten werden auf Status/Result/Notes normalisiert; Status kommt aus dem Runtime-Ergebnis (nicht aus dem Modelltext).
  • Sub-Agent-Sessions werden nach agents.defaults.subagents.archiveAfterMinutes automatisch archiviert (Standard: 60).
  • Announce-Antworten enthalten eine Statistik-Zeile (Laufzeit, Tokens, sessionKey/sessionId, Transkript-Pfad und optionale Kosten).

Sandbox-Session-Sichtbarkeit

Session-Tools koennen eingeschraenkt werden, um Cross-Session-Zugriff zu reduzieren.

Standardverhalten:

  • tools.sessions.visibility steht standardmaessig auf tree (aktuelle Session + gespawnte Subagent-Sessions).
  • Fuer sandboxed Sessions kann agents.defaults.sandbox.sessionToolsVisibility die Sichtbarkeit hart begrenzen.

Config:

{
  tools: {
    sessions: {
      // "self" | "tree" | "agent" | "all"
      // Standard: "tree"
      visibility: "tree",
    },
  },
  agents: {
    defaults: {
      sandbox: {
        // Standard: "spawned"
        sessionToolsVisibility: "spawned", // oder "all"
      },
    },
  },
}

Hinweise:

  • self: nur der aktuelle Session-Key.
  • tree: aktuelle Session + von der aktuellen Session gespawnte Sessions.
  • agent: jede Session der aktuellen Agent-ID.
  • all: jede Session (Cross-Agent-Zugriff erfordert weiterhin tools.agentToAgent).
  • Wenn eine Session sandboxed ist und sessionToolsVisibility="spawned", begrenzt OpenClaw die Sichtbarkeit auf tree, selbst wenn du tools.sessions.visibility="all" setzt.