← KI-Agenten

KI in der Praxis · Teil 1

Levels of working with AI

From a chat window to autonomous agents: ten levels of interacting with AI, what each one needs, with code for the API, tool use and agent loops, and how to choose the right level.

AgentsAPITool useMCPaktualisiert 18. Okt. 2026Englisch

The ladder at a glance

Most confusion about agents comes from mixing levels. Using Copilot in a notebook, calling a model from a script and running an unattended agent are three different things, with different setup, cost and risk. Here are ten levels, grouped into four tiers.

Tier Level What you do Who runs the loop Data engineering example
Use 1. Chat window Paste a question, read the answer You Explain a Spark stack trace
2. Assistant in your tool Ask inside the notebook or editor, which shares its context You Copilot in a Fabric notebook, Genie Code in Databricks
3. Grounded chat Give it standing context: instructions, files, retrieved documents You A project holding your naming rules and schema docs
Configure 4. Configured agent Choose the data, write instructions and examples. The platform runs the agent The platform A Genie space, a Fabric data agent
Build 5. API call A script calls a model with a key Your code, one call Write descriptions for 400 columns
6. Tool use The model asks for a function, your code runs it Your code, one step Answer “how many rows?” by calling a function
7. Agent loop The model plans and repeats tool calls until the task is done Your code or a harness A coding agent fixing a failing pipeline
Scale 8. Shared tools Package tools and know-how once (MCP, skills) for many agents A protocol Managed MCP servers, Fabric MCP server, agent skills
9. Multi-agent An orchestrator routes work to specialist agents The orchestrator A supervisor choosing between a SQL agent and a docs agent
10. Autonomous Runs on a schedule or an event with nobody watching A scheduler or platform Failure triage that opens a ticket overnight

Two more things sit outside the ladder and apply at every level: the model you pick (a small fast model for bulk work, a large one for planning) and evaluation, which gets its own section below.

Tier 1: Use

Level 1: the chat window

You copy code or an error in, read the answer, and copy the result back. It needs no setup and it is where almost everyone starts.

Good for: explaining unfamiliar code, drafting a regex or a SQL window function, understanding an error. The model sees only what you paste.

Watch for: never paste secrets, credentials or customer data. Check your organisation’s rules and the tool’s data-handling terms first.

Level 2: an assistant inside your tool

The assistant lives in the notebook, SQL editor or pipeline designer and sees its context: attached tables, schemas, the code in front of you. That context is why it is more accurate than a chat window. Examples are Copilot in Fabric notebooks and Data Factory, and Genie Code in Databricks. Parts 2 and 3 cover them in detail.

You are still the loop. You read each suggestion and decide.

Level 3: grounded chat

Here you give the model standing context so you stop repeating yourself: a project or custom instructions with your conventions (“bronze tables are append-only, silver uses merge”), attached files such as the data dictionary, or documents retrieved on demand.

For a data team the highest-value context is small and boring: naming standards, the medallion layer rules, how a metric is defined, and a list of tables people should not use.

Tier 2: Configure

Level 4: a configured agent

Now the platform runs the agent loop and you configure it. You pick the data it can use, write instructions, and add example questions with the right SQL. Two examples:

  • Genie spaces in Databricks.
  • Fabric data agents in Microsoft Fabric.

This is the right level for letting analysts ask questions of governed data, because it needs no code, runs with the asking user’s permissions, and the platform handles the plumbing. The limit is flexibility: you shape it with instructions and examples, not with logic. Parts 2 and 3 show how to configure each one.

Tier 3: Build

At this tier you write code. The three levels build directly on each other, so it is worth seeing all three.

Level 5: an API call with a key

You call the model from a script or notebook. You need an API key (or platform credentials), you pay per token, and each call stands alone.

import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY from the environment

columns = ["cust_no", "ord_dt", "net_rev_chf"]
response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": f"Write a one-line business description for each column of a "
                   f"sales fact table: {columns}. Reply as JSON {{column: description}}.",
    }],
)
print(next(b.text for b in response.content if b.type == "text"))

This is still not an agent. The model answers once, and your code decides what happens next. It is the right level for bulk, repeatable text work: documentation for hundreds of columns, classifying free-text fields, summarising run logs.

Handling keys. Keep them out of notebooks and repositories. Use environment variables locally and the platform’s secret store in the cloud:

# Databricks notebook
api_key = dbutils.secrets.get(scope="ai", key="anthropic-api-key")

# Fabric notebook
api_key = notebookutils.credentials.getSecret("https://<your-vault>.vault.azure.net/", "anthropic-api-key")

client = anthropic.Anthropic(api_key=api_key)

The same ideas apply to other providers’ APIs, such as Azure OpenAI. Only the SDK calls differ. For large batches, look at the provider’s batch endpoint, which is cheaper for work that is not urgent. For machine-readable output, use structured outputs instead of asking nicely for JSON.

Level 6: tool use (functions)

Now you describe your functions to the model. It cannot run them. It answers with a request: “call row_count with this table”. Your code runs the function and returns the result. This is the step that connects a model to your data without giving it direct access.

import anthropic

client = anthropic.Anthropic()
MODEL = "claude-opus-5-5"
ALLOWED_TABLES = {"gold.sales.fct_orders", "gold.sales.dim_customer"}

def row_count(table: str) -> str:
    if table not in ALLOWED_TABLES:  # the model proposes, your code decides
        return f"Table {table} is not allowed."
    # run SELECT COUNT(*) on your SQL warehouse here; stubbed for the example
    return "1250431"

tools = [{
    "name": "row_count",
    "description": "Return the number of rows in a table. Read-only.",
    "input_schema": {
        "type": "object",
        "properties": {
            "table": {"type": "string", "description": "Fully qualified name, e.g. gold.sales.fct_orders"}
        },
        "required": ["table"],
    },
}]

messages = [{"role": "user", "content": "How many rows are in gold.sales.fct_orders?"}]
response = client.messages.create(model=MODEL, max_tokens=1024, tools=tools, messages=messages)

if response.stop_reason == "tool_use":
    call = next(b for b in response.content if b.type == "tool_use")
    messages.append({"role": "assistant", "content": response.content})
    messages.append({"role": "user", "content": [
        {"type": "tool_result", "tool_use_id": call.id, "content": row_count(**call.input)},
    ]})
    response = client.messages.create(model=MODEL, max_tokens=1024, tools=tools, messages=messages)

print(next(b.text for b in response.content if b.type == "text"))

Three design rules show up already. Validate every input the model sends (here, an allow-list of tables). Give each function one narrow job and a precise description. Make the dangerous ones impossible, not just discouraged: read-only connections, not “please do not write”.

Level 7: the agent loop

Wrap level 6 in a loop and you have an agent. The model calls a tool, reads the result, decides the next step, and repeats until it is done. What separates a useful agent from a runaway one is the stop conditions and the gates you put around the loop:

MAX_STEPS = 8
NEEDS_APPROVAL = {"run_sql_write", "deploy_pipeline"}

for step in range(MAX_STEPS):
    response = client.messages.create(model=MODEL, max_tokens=4096, tools=tools, messages=messages)
    messages.append({"role": "assistant", "content": response.content})
    if response.stop_reason != "tool_use":
        break  # finished, or stopped for another reason: check response.stop_reason

    results = []
    for call in (b for b in response.content if b.type == "tool_use"):
        if call.name in NEEDS_APPROVAL and input(f"Run {call.name}({call.input})? [y/N] ") != "y":
            output, is_error = "Declined by the user.", True
        else:
            output, is_error = run_tool(call.name, call.input), False  # your dispatcher
        results.append({"type": "tool_result", "tool_use_id": call.id, "content": output, "is_error": is_error})
    messages.append({"role": "user", "content": results})  # all results in one message
else:
    print("Stopped: step limit reached")

Four things make this safe enough to use: a step limit, an approval gate on anything that changes state, errors returned to the model as results (so it can recover), and a full log of the messages. The SDKs also offer helpers that run this loop for you, but writing it once by hand shows what the products below are doing.

Coding agents such as Claude Code, GitHub Copilot’s agent mode and Genie Code are this loop, already built, with file and shell tools and an approval system. Most engineers use level 7 through a product, not by writing the loop.

Tier 4: Scale

Level 8: shared tools with MCP and skills

When several agents need the same tools, defining them separately in each is wasteful and unsafe. The Model Context Protocol (MCP) packages tools once, as a server, so any compatible client can use them. Databricks provides managed MCP servers, Microsoft provides a Fabric MCP server, and dbt provides an MCP server for project metadata.

Skills are the other half. A skill is a written instruction file that teaches an agent how to do a kind of work in your platform. Databricks puts it this way: skills teach the agent how to work; MCP servers let it do the work. Parts 2 and 3 show the real servers and install commands.

What changes at this level is governance: one place to control which tools exist, who can call them, and what is logged.

Level 9: multi-agent

An orchestrator receives the request and routes it to specialist agents: one that knows sales data, one that searches documentation, one that creates tickets. Both platforms support this. A Databricks supervisor agent can orchestrate Genie agents, agent endpoints, Unity Catalog functions and MCP servers. A published Fabric data agent can be called by external orchestrators such as Copilot Studio and Azure AI Foundry.

Use it when one agent’s tool list has grown so long that it picks wrongly, or when different domains have different owners and permissions. Do not start here. Every added agent multiplies what you have to test.

Level 10: autonomous agents in production

The agent runs on a schedule or on an event with nobody watching, for example triaging every failed pipeline run overnight. This is where all the earlier concerns become requirements:

  • a narrow scope and a dedicated identity with the least privilege that works,
  • budgets for steps, tokens and cost, with a hard stop,
  • a sandbox: no production writes, only recommendations and tickets at first,
  • an evaluation set that runs on every change,
  • logging and alerting on what the agent did and why.

Fabric’s operations agent for pipelines, covered in Part 2, is an example of this level as a product: it watches pipeline health and sends insights to Teams.

Two things that matter at every level

Context is the real lever

A model can only use what it can read. A star schema with clear names, documented columns and one definition per metric is the best prompt you will ever write, and it helps every human reader too. Put the rules into the platform, not into a chat window:

-- Databricks SQL: descriptions live in Unity Catalog, so every tool and agent sees them
COMMENT ON TABLE gold.sales.fct_orders IS
  'One row per order line. Grain: order_id + line_no. Revenue is net of discounts and excludes VAT.';

ALTER TABLE gold.sales.fct_orders ALTER COLUMN net_revenue
  COMMENT 'Net revenue in CHF after discounts, excluding VAT. Use this for all revenue questions.';

Three habits pay off on both platforms:

  • Name the grain of every fact table in its description.
  • Precompute awkward logic. An is_last_complete_month flag in the date dimension is safer than hoping an agent writes the right date arithmetic every time.
  • Define each metric once, in a semantic model, a metric layer or a documented view, and tell the agent to use it.

Evaluate like you test pipelines

Anything that answers questions or changes code needs a test suite. Keep a small file of golden questions beside the configuration:

- question: Net revenue by product category last month
  expected_sql: |
    SELECT p.category, SUM(f.net_revenue) FROM ...
  must_match: result_set   # compare results, not SQL text
- question: How many active customers do we have in Switzerland?
  expected_sql: |
    SELECT COUNT(*) FROM dim_customer WHERE country = 'CH' AND is_active
  must_match: result_set

Run every question after each change to instructions, examples or schema, and compare the result sets, not the SQL text, because many different queries are correct. When a real user finds a wrong answer, add it to the file before fixing it.

Choosing the level

The job looks like… Use level Why
A one-off question or explanation 1 No setup, no risk
Writing code inside a notebook or editor 2 Context comes for free
Applying the same conventions repeatedly 3 Standing context saves effort
Analysts asking questions of governed data 4 Platform-run, permission-aware, no code
The same transformation on hundreds of items 5 Cheap, repeatable, easy to test
An assistant that needs live data or system access 6 Your functions are the safety boundary
An open-ended task with several steps 7 The model must adapt as it learns
Many tools or many assistants 8 Define and govern once
Several domains with separate owners 9 Split by responsibility
Work that must happen with nobody watching 10 Only with budgets, a sandbox and evaluation

Move up a level only when the lower one has clearly run out: you need repeatability (3, 4), volume (5), live data (6), adaptability (7), reuse (8), separation (9) or unattended operation (10).

Controls grow with the level

The higher you go, the more of these you need. Treat them as a checklist:

  • Start read-only. Allow writes only in development and only with approval.
  • One identity per agent with the least privilege that works. No shared admin tokens.
  • Keep secrets out of prompts, instructions, notebooks and repositories.
  • Review every generated diff. Treat the agent like a fast, confident junior engineer.
  • Treat what an agent reads as untrusted. Tickets, documents and table comments can contain instructions aimed at it.
  • Set limits: steps, tokens, rows returned, and spend.
  • Log what was asked, what was called, and what changed.
  • Say clearly in the interface what the agent can and cannot answer.

Where to go next

Sources

Code on this page was written for this guide and is illustrative.