DuckDB-CLI mit Agent-Modus: Wie die Kommandozeile mit KI-Agenten spricht

Gummiente neben einer dunklen Terminal-Tastatur, ein Lichtband führt vom Rechner weg
Deine Reaktion:

123.600 Token auf der einen Seite, 50.800 auf der anderen. Dazwischen liegt der Effekt, den der Agent-Modus in der DuckDB-Kommandozeile in einer Messung erzielt hat, die das DuckDB-Team selbst veranlasst hat. 59 Prozent weniger Text musste ein Sprachmodell lesen, um dieselben Fragen richtig zu beantworten. Den Agent-Modus gibt es seit DuckDB v2.0 in der Shell, vorgestellt hat ihn das DuckDB-Team am 9. Oktober. Er ändert nichts an der Datenbank, wohl aber daran, wie ihre Ausgabe aussieht und wann die Shell eine ausufernde Abfrage stoppt.

Warum das nötig war, zeigt eine einfache Vorstellung. Ein Mensch am Terminal kann mit einem Ergebnis umgehen: hochscrollen, zurückblättern, nochmal nachfragen. Ein KI-Agent bekommt einen einzigen Blick. Er sieht, was durch die Pipe kommt, einmal, und alles, was nicht in diesem Text steht, existiert für ihn nicht. Nachfordern geht nicht, nachfragen auch nicht, und jedes Zeichen kostet — auch die Rahmenlinien und Leerzeichen, mit denen die CLI Spalten ausrichtet. Hier setzt der Agent-Modus an. Die Idee dahinter: Die Ausgabe soll für einen Leser gebaut sein, der nur einmal hinschaut.

Agentenerkennung: Wie DuckDB einen KI-Agenten erkennt

AI Coding Agents wie Claude Code, Codex, Cursor, Gemini CLI oder GitHub Copilot markieren ihre Befehle mit Umgebungsvariablen. Eine einheitliche Konvention gibt es nicht, also prüft die Shell eine ganze Liste. Claude Code, Goose und Amp setzen AI_AGENT oder AGENT, Claude Code zusätzlich CLAUDECODE. Codex nutzt CODEX_CI, CODEX_SANDBOX und CODEX_THREAD_ID, Cursor setzt CURSOR_AGENT, Gemini CLI setzt GEMINI_CLI, GitHub Copilot bringt COPILOT_AGENT, COPILOT_CLI und COPILOT_AGENT_SESSION_ID mit. Taucht eine dieser Variablen auf, weiß die Shell, dass ihr Gegenüber wahrscheinlich kein Mensch ist.

Das allein reicht nicht. Der Modus springt erst an, wenn drei Bedingungen zusammenkommen: eine der Variablen ist gesetzt, die Standardausgabe ist kein Terminal, und es wurde kein Ausgabeformat über die Kommandozeile vorgegeben. Wer -csv, -json oder -markdown übergibt, hat sich bewusst für ein Format entschieden, und der Agent-Modus hält sich raus. Zwei Flags überstimmen die Erkennung: -agent erzwingt den Modus, -no-agent schaltet ihn ab. Beide lassen sich mit Formatflags kombinieren, -agent -csv behält also das Agent-Verhalten und ändert nur die Darstellung der Zeilen. Mit .show prüfst du jederzeit, ob der Modus aktiv ist und welcher Agent erkannt wurde.

Nicht jeder Agent setzt eine passende Variable. Für diese Fälle gibt es einen leisen Hinweis: Scheitert ein Lauf beim Schreiben in eine Pipe, ohne dass ein Agent identifiziert wurde und ohne dass ein Flag gesetzt war, erscheint eine einzige Zeile auf stderr. Ein Agent, dem niemand vom Modus erzählt hat, kann ihn so beim ersten Fehler selbst entdecken.

Wie der Agent-Modus die Ausgabe für KI-Agenten optimiert

Im Agent-Modus druckt DuckDB Ergebnisse als Markdown-Tabellen ohne Ausrichtungs-Padding, mit dem Spaltentyp direkt in der Kopfzelle. Ein Modell liest die senkrechten Striche als Trennzeichen und braucht keine sauber ausgerichteten Spalten. Weil das weiterhin gültiges Markdown ist, bekommt auch ein Mensch, der später das Transkript liest, eine ordentlich gerenderte Tabelle. Auf typischen Ergebnissen ist dieses Format 25 bis 65 Prozent kleiner als die Kasten-Darstellung, bei breiten Ergebnissen am stärksten.

Bei der Ausgabemenge steckt der eigentliche Kniff. Alle Zeilen zu drucken würde stille Kürzungen vermeiden, aber eine Million Zeilen sind schnell 17 Megabyte durch die Pipe. Deshalb gibt der Agent-Modus ein Ergebnis bis 1.000 Zeilen und 10.000 Byte vollständig aus. Alles darüber wird zu einer Stichprobe aus den ersten und letzten 20 Zeilen, dazwischen eine explizite Markierungszeile, und eine Fußzeile erklärt, was passiert ist. Diese Fußzeile sagt auch, wie du den Rest bekommst. Die Grenzen passen sich mit .maxrows N und .maxbytes N an, -1 oder 0 steht für „kein Limit“. Lange Zellwerte werden bei 500 Zeichen abgeschnitten, mit sichtbarem Marker wie …(+4500 chars), steuerbar über .maxcellwidth N. Alle diese Werte sind nur Voreinstellungen: Ausdrückliche Einstellungen wie .mode, .maxrows, EXPLAIN (FORMAT …) oder Einträge in der .duckdbrc haben weiterhin Vorrang.

Ein Detail, das leicht übersehen wird: Die Fußzeile enthält einen Hash des gesamten Ergebnisses, auch der Zeilen jenseits der Kappungsgrenze. Der Hash ist unabhängig von der Zeilenreihenfolge und unterscheidet NULL von der Zeichenkette ‚NULL‘. Ein Agent, der wissen will, ob sich ein Ergebnis nach einer Änderung verschoben hat, vergleicht zwei Fußzeilen statt zwei vollständige Ausgaben. Die Fußzeile erscheint bei leeren Ergebnissen, ab zehn Zeilen und immer, wenn die Ausgabe gekappt wurde. Nur wenn die Abfrage früh abgebrochen wurde, fehlt sie — dann würde der Hash nicht das ganze Ergebnis abdecken.

Abgebrochene Abfragen und Kosten vor dem Start

Die kompakte Tabelle braucht keine Spaltenbreiten, deshalb kann das Ergebnis gestreamt werden. Ist die Obergrenze erreicht, werden die restlichen Zeilen nur noch gezählt und gehasht. Nach weiteren 100.000 Zeilen stoppt die Shell die Abfrage und meldet die Zahl als Untergrenze. Das Beispiel im Beitrag, eine Abfrage über eine Milliarde generierte Zeilen mit FROM range(1_000_000_000), liefert so in 30 Millisekunden ein Ergebnis, begleitet von der Fußzeile „first 20 of at least 102400 rows“. Wer wirklich alles sehen will, setzt .maxrows -1 und nimmt die Wartezeit in Kauf.

Noch einen Schritt früher greift die Kostenschätzung. Erwartet der Planer, dass eine Anweisung eine Million Zeilen oder mehr liest, geht seine Schätzung noch vor der Ausführung an stderr. Der Agent kann dann entscheiden, ob er wartet oder abbricht und die Abfrage umschreibt. Kleinere Abfragen geben nichts aus, die Zeile wäre nur Rauschen. Während eine lange Abfrage läuft, ersetzt eine schlichte Zeile auf stderr alle fünf Sekunden den Fortschrittsbalken, den ein Mensch im Terminal gewohnt ist.

Fehler als JSON und kompakte Query-Pläne

Fehler landen im Agent-Modus als JSON auf stderr, gesteuert über die bestehende errors_as_json-Einstellung. Auch Fehler, die die Shell selbst wirft — etwa ein unbekannter Punkt-Befehl —, werden in dieselbe Struktur verpackt. Ein Feld namens candidates fällt weg, weil die Meldung die Kandidaten ohnehin auflistet. Ohne diese Änderung wiegt ein einzelner „no matching function“-Fehler 2,7 Kilobyte, die ein Modell erst durcharbeiten muss.

Auch der Ausführungsplan schrumpft. EXPLAIN nutzt standardmäßig ein neues compact-Format mit einem Operator pro Zeile, eingerückt nach Tiefe; Schätzungen, tatsächliche Zeilenzahlen und Zeiten stehen in Klammern, gefolgt von den Eigenschaften des Operators. EXPLAIN ANALYZE beginnt mit einer Zusammenfassungszeile wie „QUERY (time=0.0012s, read=1.2 MB)“. Das ist ein reguläres Format, du kannst also auch außerhalb des Agent-Modus EXPLAIN (FORMAT compact) verwenden. Beim Schema hilft .tables, das jetzt eine Zeile pro Tabelle mit ungefährer Zeilenzahl und Spaltenliste ausgibt — durch eine Pipe deutlich lesbarer als das übliche Kastenlayout. Und beim Start druckt die Shell genau eine Zeile auf stderr, die erklärt, warum der Modus an ist und wie man ihn abschaltet. Die ausführliche Erklärung holst du dir bei Bedarf über .help agent, wo auch Hinweise auf SET max_execution_time, DESCRIBE, SUMMARIZE und duckdb_functions() stehen.

Die ehrliche Token-Bilanz: 59 Prozent sind nicht 59 Prozent

Nun zur Messung, mit der alles begann. Gemessen hat das DuckDB-Team nicht selbst, es hat Claude damit beauftragt: Claude Code beantwortete die 22 TPC-H-Fragen auf einem Datensatz der Skalierung 100 und schrieb Aufbau und Ergebnisse anschließend in einem Bericht zusammen. Es ist also eine Messung im Auftrag des Herstellers, kein unabhängiger Benchmark. Die Fragen waren in einfachem Englisch formuliert, ohne SQL. Jede Frage wurde dreimal mit Agent-Modus und dreimal mit -no-agent beantwortet. Alle 132 Läufe lieferten die richtige Antwort. Die Ausgabe, die das Modell lesen musste, schrumpfte von 123.600 auf 50.800 Token, also um 59 Prozent. Das ist die Token-Einsparung, um die es in der ganzen Diskussion geht.

Diese Zahl klingt spektakulärer, als sie ist, und der Bericht räumt das selbst ein. Die Einsparung tauchte weder in den Gesamtkosten noch in der Laufzeit nennenswert auf. Der Grund: In jedem Zug liest das Modell seinen eigenen System-Prompt erneut, und der ist deutlich größer als die Abfrageausgabe. Unterm Strich machten die gesparten Token etwa 0,5 Prozent der gesamten Eingabe aus. Die Läufe mit Agent-Modus brauchten sogar leicht mehr Schritte — 237 gegenüber 224. Claude Fable 5.1 fasste das Ergebnis so zusammen: Der Modus repariere die Dinge, die in einer Terminal-Shell ein Modell still in die Irre führen, und die gelesenen Token sanken um rund 60 Prozent, während jede Antwort weiterhin stimmte. Eine präzise, aber bewusst begrenzte Aussage.

Ausprobieren: Was Nutzer von Coding-Agenten tun müssen

Für die Praxis ist die Sache unspektakulär: Wer einen Coding-Agenten nutzt, muss nichts konfigurieren. Claude Code, Codex, Cursor, Gemini CLI und GitHub Copilot setzen bereits eine der Variablen und fangen die Ausgabe über eine Pipe ab — zwei der drei Bedingungen sind damit erfüllt. Solange die duckdb-Binary im Pfad des Agenten Version 2.0 oder neuer ist und kein Formatflag wie -csv, -json oder -markdown im Spiel ist, schaltet sich der Modus von selbst ein. Ein Formatflag gilt bewusst als Entscheidung, deshalb überstimmt es den Agent-Modus. Um zu sehen, was der Agent sieht, schickst du eine Abfrage mit gesetztem Flag durch eine Pipe — dann bekommst du genau das, was ein Modell zu lesen bekäme.

Der Agent-Modus ist kein Kostenturbo, und er macht ein Modell nicht klüger. Er räumt eine bestimmte Schwäche aus dem Weg: Ein Agent soll ein Ergebnis nicht für vollständig halten, wenn es nur ein Ausschnitt ist, und er soll nicht für Rahmenlinien bezahlen, die ihm nichts sagen. Das ist eine Designentscheidung für einen Leser, der nur einmal hinschaut. So gesehen ist der Modus weniger ein neues Feature als eine Korrektur an einem Werkzeug, das für Augen gebaut wurde, die zurückblättern können. Der Rest ist Feinschliff an den Konventionen, und da ist die Sache noch im Fluss: Das DuckDB-Team nennt das aktuelle Verhalten selbst einen ersten Versuch und bittet um Rückmeldungen, wenn ein Agent nicht erkannt wird oder die Ausgabe ihn verwirrt.

Quelle: duckdb.org

Deine Reaktion:
Artikel teilen:
Krötzsch-Check0 — 100
Fakten 78
Relevanz 74
Hype 25
Einschätzung 71
Redaktion 50 Stand 50 · noch keine Stimmen
Ist das Hype?
Sebastian Krötzsch
Autor

Sebastian Krötzsch

Sebastian Krötzsch schreibt auf sebask.de über Künstliche Intelligenz, Automatisierung, digitale Systeme und die Frage, was davon im Alltag wirklich nützlich ist. Ohne Buzzword-Nebel, dafür mit klarem Blick auf Praxis, Tools und echte Wirkung.