Multi-Agen­ten Sys­teme in Text-to-SQL: Zukunft der Datenanalyse?



Multi-Agen­ten Sys­teme in Text-to-SQL: Zukunft der Datenanalyse?

Über­mä­ßige Daten­men­gen kön­nen User in Unter­neh­men oft über­for­dern. Des­we­gen blei­ben die tie­fe­ren Erkennt­nisse, die diese Daten bie­ten, lei­der oft ver­bor­gen. Hier setzt Multi-Agent Text-to-SQL an: Durch den Ein­satz moder­ner KI-Agen­ten kön­nen auch nicht-tech­ni­sche Nut­zer Daten über natür­li­che Spra­che abfra­gen und prä­zise Queries generieren.

Zugäng­li­che Ver­ar­bei­tungs­me­tho­den, die auch nicht-tech­ni­schen Nut­zern Zugriff auf diese Erkenn­tisse bie­ten, beinhal­ten oft Tech­ni­ken mit­tels gene­ra­ti­ver AI (GenAI).

GenAI bedient sich dabei zumeist Large Lan­guage Models (LLMs), die aus bereit­ge­stell­tem Kon­text pro­ba­bi­lis­tisch Text, Bil­der oder auch Musik erzeu­gen können.

Aller­dings hal­lu­zi­nie­ren LLMs häu­fig Fak­ten und prä­sen­tie­ren nicht akku­rat die Erkennt­nisse der zuge­hö­ri­gen Datenbank.

Hier schaf­fen neue Ansätze Abhilfe, indem sie die Auf­ga­ben auf meh­rere KI-Agen­ten ver­tei­len. Bei­spiels­weise wer­den fak­ten­ba­sierte Ant­wor­ten gelie­fert, indem eine Daten­bank mit­tels Text-to-SQL (Struc­tu­red Query Lan­guage) abge­fragt wird und der zustän­dige Agent diese Erkennt­nisse in sei­ner Ant­wort nutzt.

Damit wird auch nicht-tech­ni­schen Usern die Mög­lich­keit gebo­ten, auf direk­tem Level Erkennt­nisse aus einer Daten­bank zu extrahieren.

Gren­zen klas­si­cher LLM Ansätze:

Bis­her ver­lie­ßen sich viele KI-Archi­tek­tu­ren auf Retrie­val-Aug­men­ted Gene­ra­tion (RAG) mit­tels Vektordatenbanken.

Wäh­rend diese Ansätze effek­tiv Daten mit ähn­li­chen Stich­wor­ten fin­den, schei­tern sie oft an fort­ge­schrit­te­nen Anfra­gen, die wei­ter­füh­ren­den Kon­text oder Logik erfor­dern. Bei­spiels­weise erfor­dern tie­fer­ge­hende SQL Queries oft Aggre­gate und Ver­knüp­fun­gen meh­re­rer Tabel­len mit­hilfe von Joins anhand bestimm­ter Spalten.

Dar­über­hin­aus füh­ren rein pro­ba­bi­lis­ti­sche Ansätze oft zu Hal­lu­zi­na­tio­nen, wes­we­gen ein deter­mi­nis­ti­scher Ansatz für belast­bare Aus­sa­gen unum­gäng­lich ist.

Der deter­mi­nis­ti­sche Aus­weg: Text-to-SQL

Im Multi-Agent Text-to-SQL Ansatz wer­den die Gren­zen der LLMs mit­tels deter­mi­nis­ti­scher Leit­plan­ken erweitert.

Die Arbeits­schritte wer­den auf ver­schie­dene KI-Agen­ten aufgeteilt:

  • Ein LLM wird nur dazu ange­hal­ten, eine SQL-Query zu erzeugen.
  • Die Vali­die­rung der erstell­ten Logik und das Erzeu­gen des Resul­tats erfolgt direkt gegen die zugrun­de­lie­gende Daten­bank. Hal­lu­zi­na­tio­nen von Fak­ten sind damit ausgeschlossen.

Um eine ein­fa­chere Hand­ha­bung der Daten und LLMs zu gewähr­leis­ten, eröff­nen moderne Tech­no­lo­gien wie das Model Con­text Pro­to­col (MCP) Mög­lich­kei­ten, um KI-Agen­ten direkt mit den Daten­ban­ken zu verknüpfen.

Archi­tek­tur eines moder­nen Multi-Agenten-Systems

Durch gestei­gerte Kom­ple­xi­tä­ten im Arbeits­all­tag wer­den auch die zuge­hö­ri­gem Daten immer viel­schich­ti­ger. Des­we­gen las­sen sich reale Daten­ban­ken von moder­nen Unter­neh­men sich nicht mehr als ein­fa­che Tabelle dar­stel­len, son­dern ent­hal­ten eine Viel­zahl von ver­zahn­ten Objekten.

Daher müs­sen oft Infor­ma­tio­nen aus ver­schie­de­nen Quel­len kom­bi­niert wer­den, um Anfra­gen voll­um­fäng­lich zu beantworten.

Dabei würde es das Kon­text­fens­ter über­la­den, einem LLM die Gesamt­heit der Daten­struk­tur mitzuteilen.

Der hier vor­ge­stellte Aus­weg ist eine Archi­tek­tur, die meh­rere KI-Agen­ten hin­ter­ein­an­der schal­tet, um die Auf­ga­ben und Her­aus­for­de­rung auf­zu­tei­len. Dar­über­hin­aus ermög­li­chen Tech­no­lo­gien, feh­ler­hafte Queries direkt zu kor­ri­gie­ren oder bei bedenk­li­chen Queries den User nach einer Frei­gabe zu fra­gen (Human-in-the-loop).

Archi­tek­tur-Skizze eines Multi-Agent Text-to-SQL Sys­tems mit KI-Agen­ten, in der die User-Anfrage schritt­weise ver­ar­bei­tet wird. Dazu erstellt der Skim­mer im ers­ten Layer den Kon­text für die Daten­bank, wobei ein seman­ti­sches Layer hilft, Anfra­gen rich­tig zu ver­ste­hen. Anschlie­ßend erzeugt der Coder-Agent die SQL-Query, wobei als Sicher­heits­layer mit­tels einer Human-in-the-loop Inter­ak­tion rea­li­siert wird. Abschlie­ßend wird die Query aus­ge­führt und die finale Ant­wort aus den Fak­ten formuliert.

Kon­text­fil­ter

Ein vor­ge­schal­te­ter Agent fun­giert als „Skim­mer“. Seine Auf­gabe ist es, die gestellte Anfrage zu ver­ste­hen und nur die für die Ant­wort benö­tig­ten Tabel­len und Spal­ten zu identifizieren.

Hier­bei fin­den die bereits erwähn­ten RAG-basier­ten Vek­tor­su­chen wei­ter­hin Anwen­dung, diese wer­den nicht ersetzt son­dern erwei­tert im Multi-Agen­ten-Sys­tem. Durch das bes­sere Ver­ständ­nis der Daten­bank kann im nächs­ten Schritt eine bes­sere Abfrage erzeugt werden.

Inte­grierte Korrekturloops

Moderne Sys­teme nut­zen Agen­ten-Frame­works wie Lang­Graph, um stra­te­gi­sche Pläne zu for­mu­lie­ren. Sollte eine gene­rierte Query fehl­schla­gen, ana­ly­siert das Sys­tem den Feh­ler, nutzt den bis­he­ri­gen Kon­text und star­tet einen auto­ma­ti­schen Kor­rek­tur­loop ohne eine erneute Anfrage zu benö­ti­gen. Dadurch wird der gesamte Work­flow sta­bi­ler ohne zusätz­li­che mensch­li­che Inputs zu erfordern.

Seman­ti­sche Schicht

Da mensch­li­che Anfra­gen oft vage oder mehr­deu­tig for­mu­liert sind („Was ist das beste Pro­dukt?“), hilft eine vor­ge­fer­tigte seman­ti­sche Schicht, die für der­lei Anfra­gen wei­te­ren Kon­text bereit­stellt („Metrik für Pro­dukte: Umsatz, Absatz­zah­len“). Dar­aus kön­nen vom zustän­di­gen Agen­ten dann kon­krete Abfra­gen abge­lei­tet wer­den („Sum­miere Spalte Umsatz für Tabelle Ver­käufe“), die idea­ler­weise die tat­säch­li­che Inten­tion des Fra­gen­den abbilden.

Uni­ver­sa­li­tät durch MCP

Das MCP Pro­to­koll erlaubt die Anbin­dung von Agen­ten an diverse ver­füg­bare Tools. Hier­bei fun­giert das MCP Pro­to­koll als eine stan­dar­di­sierte Brü­cke unter Benut­zung einer uni­ver­sel­len Schnitt­stelle. Dadurch ist die Archi­tek­tur nicht auf ein bestimm­tes LLM als Agen­ten fest­ge­setzt, son­dern es kann für jede Ebene der pas­sende Agent ein­ge­setzt wer­den. (MCP-Web­i­nar)

Sicher­heit via Human-in-the-loop

Über­eif­rige KI-Agen­ten könn­ten in pro­duk­ti­ven Daten­ban­ken erheb­li­chen Scha­den anrich­ten, wenn bei­spiels­weise Daten unge­wollt gelöscht wer­den. Hier schafft eine „Human-in-the-Loop“-Architektur Sicher­heit. Kri­ti­sche Befehle oder die Ver­öf­fent­li­chung sen­si­bler Daten wer­den erst nach expli­zi­ter Frei­gabe durch einen Men­schen aus­ge­führt. Wie im Bei­spiel unten auf­ge­führt, erkennt das Sicher­heits­layer gefähr­li­che Syn­tax in den Abfra­gen, bricht die Aus­füh­rung ab und war­tet auf eine expli­zite mensch­li­che Erlaubnis. 

Ver­gleich LLM gegen Mensch

Als belast­bare Metrik für die Per­for­mance von Text-to-SQL Ansät­zen hat sich Bird-SQL (Big Bench for large-scale Data­base-groun­ded Text-to-SQL) bewährt.

Diese ver­gleicht die Per­for­mance von SQL Abfra­gen unter Berück­sich­ti­gung von Daten­bank­struk­tur, Größe und Effi­zi­enz auf unauf­ge­räum­ten, rea­len Daten­ban­ken, die Ver­knüp­fung meh­re­rer Tabel­len erfordern.

Quan­ti­fi­ziert wird die Per­for­mance unter ande­rem mit:

1. Exe­cu­tion Accu­racy (EX): Stimmt das Ergeb­nis der KI-Query mit der hin­ter­leg­ten „Gold-Standard“-Abfrage überein?

2. Reward-based Valid Effi­ci­ency Score (R‑VES): Ver­braucht die Query unan­ge­mes­sen viel Zeit oder Speicherressourcen.

In einer Stu­die erreich­ten mensch­li­che Experten Scores von ca. 92%, wäh­rend ver­schie­dene AI Sys­teme maxi­mal ~80% erreichten.

Tech­ni­sches Beispiel:

Im Fol­gen­den wird ein­mal bei­spiel­haft die Archi­tek­tur eines Multi-Agen­ten Sys­tems gezeigt, wel­ches auf einer Dummy-Daten­bank aus natür­li­chem Text über SQL Abfra­gen deter­mi­nis­ti­sche Ergeb­nisse erzielt.

Ablauf­dia­gramm für Multi-Agent Text-to-SQL Abfra­gen im CLI. Die Ver­ar­bei­tung der User­an­frage erfolgt in einem Multi-Agen­ten-Sys­tem aus Skim­mer und Coder.

Daten­bank

Zunächst wird eine Daten­bank mit einer künst­li­chen Unter­neh­mens­da­ten mit­tels sqlite3 erstellt.

Diese ent­hält klas­si­sche Ele­mente wie Pro­dukte, Kun­den und Bestellungen.

Die Ein­träge sind der­art ange­legt, dass zur voll­stän­di­gen Beant­wor­tung von Anfra­gen Ver­knüp­fun­gen zwi­schen die­sen Tabel­len von­nö­ten sind.

– 1. Cate­go­ries Table

CREATE TABLE categories (

    category_id INTEGER PRIMARY KEY AUTOINCREMENT,

    category_name TEXT NOT NULL,

    descrip­tion TEXT

);

– 2. Pro­ducts Table

CREATE TABLE products (

    product_id INTEGER PRIMARY KEY AUTOINCREMENT,

    product_name TEXT NOT NULL,

    category_id INTEGER,

    list_price REAL NOT NULL,

    stock_quantity INTEGER,

    FOREIGN KEY (category_id) REFERENCES categories(category_id)

);

– 3. Cus­to­mers Table

CREATE TABLE customers (

    customer_id INTEGER PRIMARY KEY AUTOINCREMENT,

    company_name TEXT NOT NULL,

    coun­try TEXT,

    seg­ment TEXT – e.g., Enter­prise, SMB, Startup

);

– 4. Orders Table

CREATE TABLE orders (

    order_id INTEGER PRIMARY KEY AUTOINCREMENT,

    customer_id INTEGER,

    order_date DATE,

    sta­tus TEXT, – e.g., Ship­ped, Pen­ding, Cancelled

    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)

);

– 5. Order Items Table (The bridging table for Many-to-Many bet­ween Orders and Products)

CREATE TABLE order_items (

    item_id INTEGER PRIMARY KEY AUTOINCREMENT,

    order_id INTEGER,

    product_id INTEGER,

    quan­tity INTEGER NOT NULL,

    unit_price REAL NOT NULL, – Price at the time of sale (might dif­fer from list_price)

    FOREIGN KEY (order_id) REFERENCES orders(order_id),

    FOREIGN KEY (product_id) REFERENCES products(product_id)

);

– ==========================================

– INSERT DUMMY DATA

– ==========================================

– Insert Categories

INSERT INTO cate­go­ries (category_name, descrip­tion) VALUES

(‚Work­sta­tions‘, ‚High-per­for­mance desk­top computers‘),

(‚Peri­pherals‘, ‚Moni­tors, key­boards, and mice‘),

(‚Ser­ver Hard­ware‘, ‚Rack mounts and enter­prise networking‘);

– Insert Products

INSERT INTO pro­ducts (product_name, category_id, list_price, stock_quantity) VALUES

(‚Dev­Box Pro‘, 1, 2500.00, 50),

(‚Ultra­Wide Moni­tor 34″‘, 2, 800.00, 120),

(‚Mecha­ni­cal Key­board‘, 2, 150.00, 300),

(‚Rack Ser­ver 2U‘, 3, 5500.00, 20),

(‚Cloud Switch 48-Port‘, 3, 1200.00, 45);

– Insert Customers

INSERT INTO cus­to­mers (company_name, coun­try, seg­ment) VALUES

(‚Acme Corp‘, ‚Ger­many‘, ‚Enter­prise‘),

(‚Globex Solu­ti­ons‘, ‚USA‘, ‚SMB‘),

(‚Ini­tech‘, ‚USA‘, ‚Enter­prise‘),

(‚Soy­lent Ana­ly­tics‘, ‚UK‘, ‚Startup‘);

– Insert Orders

INSERT INTO orders (customer_id, order_date, sta­tus) VALUES

(1, ‚2026–03-10‘, ‚Ship­ped‘),

(1, ‚2026–04-05‘, ‚Pen­ding‘),

(2, ‚2026–04-12‘, ‚Ship­ped‘),

(3, ‚2026–04-18‘, ‚Ship­ped‘),

(4, ‚2026–04-20‘, ‚Pen­ding‘);

– Insert Order Items (Lin­king Orders to Products)

– Order 1 (Acme Corp): 10 Dev­Box Pros, 10 Monitors

INSERT INTO order_items (order_id, product_id, quan­tity, unit_price) VALUES

(1, 1, 10, 2400.00), – Dis­coun­ted price

(1, 2, 10, 800.00);

– Order 2 (Acme Corp): 2 Rack Servers

INSERT INTO order_items (order_id, product_id, quan­tity, unit_price) VALUES

(2, 4, 2, 5500.00);

– Order 3 (Globex): 5 Keyboards

INSERT INTO order_items (order_id, product_id, quan­tity, unit_price) VALUES

(3, 3, 5, 150.00);

– Order 4 (Ini­tech): 20 Dev­Box Pros, 1 Cloud Switch

INSERT INTO order_items (order_id, product_id, quan­tity, unit_price) VALUES

(4, 1, 20, 2500.00),

(4, 5, 1, 1200.00);

– Order 5 (Soy­lent): 2 Monitors

INSERT INTO order_items (order_id, product_id, quan­tity, unit_price) VALUES

(5, 2, 2, 800.00);

Imple­men­tie­rung der Agenten-Logik

Agent 1: Skimmer

Zur Ver­ar­bei­tung von user-Anfra­gen wird als ers­ter Agent („Skim­mer“) zum Ana­ly­sie­ren der Anfrage, durch­su­chen der Databank und Ver­an­schau­li­chung des Kon­tex­tes kreiert.

Die­ser hat nur die Auf­gabe, alle Tabel­len zusam­men­zu­tra­gen, die im Nach­gang benö­tigt wer­den, um den Kon­text für die SQL Abfrage zu erstellen.

Per Prompt gibt der Skim­mer nur eine Liste von Tabel­len zurück.

def agent_1_skimmer(state: AgentState):

    print(„🕵️ Agent 1 (Skim­mer): Revie­w­ing data­base tables…“)

    all_tables = get_all_table_names()

    system_prompt = „You are a data­base archi­tect. Your ONLY job is to iden­tify which tables are nee­ded to ans­wer the user’s question.“

    user_prompt = f“““

    Available tables: {‚, ‚.join(all_tables)}

    User Ques­tion: {state[‚question‘]}

    Return ONLY a comma-sepa­ra­ted list of the requi­red table names. No expl­ana­tion. No markdown.

    „““

    response = call_your_llm(system_prompt, user_prompt)

    # Parse the list and clean up

    selected_tables = [t.strip() for t in response.split(„,“)]

    filtered_schema = get_specific_table_schemas(selected_tables)

    print(f“   -> Tables sel­ec­ted: {selected_tables}“)

    return {„selected_tables“: selected_tables, „filtered_schema“: filtered_schema}

Agent 2: Erstel­len der SQL Query

Ein zwei­ter Agent ist der SQL Experte und erhält die Anfrage sowie die Liste der Tabel­len vom Skimmer.

Dar­auf­hin wird die Query erstellt. Um sicher­zu­ge­hen, dass nicht unfrei­wil­lig Daten gelöscht wer­den, ist eine Liste an Key­words hin­ter­legt, die eine mensch­li­che Frei­gabe erfordern.

def agent_2_coder(state: AgentState):

    print(„💻 Agent 2 (Coder): Gene­ra­ting SQL from fil­te­red schema…“)

    system_prompt = „You are a SQLite expert. Write the SQL query to ans­wer the ques­tion. Return ONLY raw SQL. No mark­down wrappers.“

    user_prompt = f“““

    Schema for rele­vant tables:

    {state[‚filtered_schema‘]}

    User Ques­tion: {state[‚question‘]}

    „““

    sql = call_your_llm(system_prompt, user_prompt)

    # Clean up SQL for­mat­ting if LLM includes markdown

    if sql.startswith(„„ ‚sql“):

        sql = sql[6:-3].strip()

    elif sql.startswith(„„ ‚“):

        sql = sql[3:-3].strip()

    # — SAFETY CHECK LOGIC —

    dangerous_keywords = [

        „DROP“,

        „TRUNCATE“,

        „DELETE“,

        „UPDATE“,

        „INSERT“,

        „ALTER“,

        „REPLACE“,

    ]

    requires_approval = any(

        re.search(rf“\b{word}\b“, sql.upper()) for word in dangerous_keywords

    )

    return {„sql_query“: sql, „requires_approval“: requires_approval}

Sicher­heits­layer: Human-in-the-loop

Wenn eine destruk­tive Query ent­deckt wird, wird direkt eine War­nung gesen­det und der Nut­zer muss diese Query erst frei­ge­ben, bevor diese gegen die Daten­bank aus­ge­führt wird.

Die Kri­te­rien, ab denen eine gene­rierte Query mensch­li­che Frei­gabe erfor­dert, kön­nen je nach Com­pli­ance-Kri­te­rien und Anfor­de­run­gen an den Usecase ange­passt werden.

def human_approval_node(state: AgentState):

    „“„This node hand­les the inter­ac­tive Human-in-the-Loop step.“““

    print(„\n“ + „⚠️ “ * 15)

    print(„🚨 WARNING: POTENTIALLY DESTRUCTIVE QUERY DETECTED 🚨“)

    print(f„Generated SQL:\n{state[’sql_query‘]}“)

    print(„⚠️ “ * 15)

    while True:

        choice = input(„\nDo you approve exe­cu­ting this query? (y/n): “).strip().lower()

        if choice in [„y“, „yes“]:

            print(„Approval gran­ted. Pro­cee­ding to execution…“)

            return {}  # State remains unch­an­ged, pro­ceeds to execution

        elif choice in [„n“, „no“]:

            print(„Execution abor­ted by human.“)

            return {

                „db_results“: „Exe­cu­tion abor­ted by human admi­nis­tra­tor due to safety concerns.“

            }

Der Usecase: Inter­ak­tion von User und Agenten

In unse­rem Bei­spiel erfolgt die Inter­ak­tion mit­tels aus­ge­führ­tem Python Script und Inter­ak­tion im CLI wie unten dargestellt.

Am Anfang wird die User­an­frage (How many products do we have?) ver­ar­bei­tet.

Dar­u­af­hin sucht der Skim­mer die benö­tig­ten Tabel­len aus der Daten­bank her­aus (‚Tables sel­ec­ted: [‚pro­ducts‘]‚) und gibt diese weiter.

Der nächste Agent, der Coder, for­mu­liert dar­aus eine Abfrage (SELECT COUNT(product_id) FROM products), wel­che keine gefähr­li­chen Schlüs­sel­wör­ter enthält.

Um die gefun­dene Ant­wort in mensch­li­che Spra­che zu über­set­zen, ist hier noch ein Inter­pre­ter-Agent geschal­tet, damit auch nicht tech­ni­sche User direkt Erkennt­nisse aus der gefun­den­den Ant­wort zie­hen können.

Im Gegen­satz dazu wird im zwei­ten Bei­spiel eine destruk­tive Anfrage gesen­det (Delete all orders).

Der Skim­mer und der Coder erzeu­gen die kor­rekte Liste an Tabel­len (Tables selected: ['orders', 'order_items', 'customers']) sowie eine rich­tige Query (DELETE FROM orders😉 um die Anfrage des Users rich­tig in SQL zu übersetzen.

Da diese Query Daten löschen würde, wird eine War­nung aus­ge­löst und der Human-in-the-loop wird gefragt, ob er diese Query frei­ge­ben möchte.

Nach der Ableh­nung erhält der User kein Ergeb­nis für seine Anfrage, statt­des­sen erscheint die War­nung The deletion of all orders was not completed. The execution was aborted by a human administrator due to safety concerns, indicating that the action may have had unintended or potentially harmful consequences .

============================================================

🕸️  Lang­Graph Multi-Agent SQL Sys­tem (Safe Mode)

============================================================

User Ques­tion: How many pro­ducts do we have?

————————————————————

🕵️ Agent 1 (Skim­mer): Revie­w­ing data­base tables…

   -> Tables sel­ec­ted: [‚pro­ducts‘]

💻 Agent 2 (Coder): Gene­ra­ting SQL from fil­te­red schema…

⚡ Sys­tem: Exe­cu­ting SQL query…

🗣️ Agent 3 (Inter­pre­ter): For­mu­la­ting final response…

==================== FINAL OUTPUT ====================

Gene­ra­ted SQL : SELECT COUNT(product_id) FROM products

Final Ans­wer  : We have 5 products.

======================================================

User Ques­tion: Delete all orders

————————————————————

🕵️ Agent 1 (Skim­mer): Revie­w­ing data­base tables…

   -> Tables sel­ec­ted: [‚orders‘, ‚order_items‘, ‚cus­to­mers‘]

💻 Agent 2 (Coder): Gene­ra­ting SQL from fil­te­red schema…

⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️

🚨 WARNING: POTENTIALLY DESTRUCTIVE QUERY DETECTED 🚨

Gene­ra­ted SQL:

DELETE FROM orders;

⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️

Do you approve exe­cu­ting this query? (y/n): n

Exe­cu­tion abor­ted by human.

🗣️ Agent 3 (Inter­pre­ter): For­mu­la­ting final response…

==================== FINAL OUTPUT ====================

Gene­ra­ted SQL : DELETE FROM orders;

Final Ans­wer  : The dele­tion of all orders was not com­ple­ted. The exe­cu­tion was abor­ted by a human admi­nis­tra­tor due to safety con­cerns, indi­ca­ting that the action may have had unin­ten­ded or poten­ti­ally harmful consequences.

======================================================

MCP: Aus­la­gern der Daten­bank in die Cloud

Die­ses Bei­spiel erfolgte der Ein­fach­heit hal­ber nur auf einer loka­len Datenbank.

Über das MCP Prot­koll las­sen sich auch ein­fach nicht nur andere LLM Agen­ten, son­dern auch bei­spiels­weise Cloud SQL Daten­banbken wie Snow­flake anbinden.

# Con­nect to Snowflake

def init_snowflake():

    user = os.getenv(„SNOWFLAKE_USER“)

    pass­word = os.getenv(„SNOWFLAKE_PASSWORD“)

    account = os.getenv(„SNOWFLAKE_ACCOUNT“)

    ware­house = os.getenv(„SNOWFLAKE_WAREHOUSE“)

    data­base = os.getenv(„SNOWFLAKE_DATABASE“)

    schema = os.getenv(„SNOWFLAKE_SCHEMA“)

    role = os.getenv(„SNOWFLAKE_ROLE“)

    conn = snowflake.connector.connect(

        user=user,

        password=password,

        account=account,

        warehouse=warehouse,

        database=database,

        schema=schema,

        role=role,

    )

    print(„✅ Con­nec­ted to Snow­flake“, sys.stderr, file=sys.stderr)

    return conn

            send(

                snow_proc,

                {

                    „jsonrpc“: „2.0“,

                    „id“: msg_id_snow,

                    „method“: „tools/call“,

                    „params“: {

                        „name“: „query_snowflake“,

                        „argu­ments“: {„query“: sql_query},

                    },

                },

            )

            result = recv(snow_q, timeout=30)            
msg_id_snow += 1

Fazit

Die vor­ge­stellte Archi­tek­tur eines Multi-Agen­ten-Sys­tems für Text-to-SQL mar­kiert einen Über­gang weg von pro­ba­bi­lis­ti­schen LLM Ansät­zen, die Fak­ten trotz zugrun­de­lie­gen­der Dat­an­bank hal­lu­zi­nie­ren hin zu einem deter­mi­nis­ti­schen Ansatz, bei dem alle Anfra­gen aus funk­tio­nie­ren­den Queries gegen eine Daten­bank beant­wor­tet werden.

Hin­weis: AI generiert.

Der Ein­satz von Lang­Graph für kom­plexe Kor­rek­tur­schlei­fen und MCP als uni­ver­selle Schnitt­stelle schafft Archi­tek­tu­ren, welche

  • Weni­ger hal­lu­zi­nie­ren, da sie auf ech­ten Daten­bank-Fak­ten basieren.
  • Effi­zi­en­ter arbei­ten, indem der vor­ge­schal­tete Skim­mer den Kon­text bereinigt.
  • Siche­rer sind, da durch Human-in-the-Loop und Sicher­heits-Layer kri­ti­sche Feh­ler ver­mie­den werden.
  • Ska­lier­bar und fle­xi­bel sind, da über MCP als uni­ver­sale Schnitt­stelle direkt andere LLM Agen­ten und Daten­ban­ken ange­bun­den wer­den können.

Zukünf­tig kön­nen auch nicht-tech­ni­sche User pro­blem­los Erkennt­nisse aus Daten­ban­ken zie­hen, ohne dass die Gefahr von Hal­lu­zi­na­tio­nen oder Daten­ver­lust besteht.