OpenGenie
Repository on GitHub

Tutorial

On this page

Time: about 30 minutes the first time. Skills needed: you can run a notebook and paste a token. You do not need a terminal on your own computer. Everything runs from a notebook in your browser, and the agent works in a small temporary Linux machine that Databricks gives you.

By the end you will have:

About the screenshots. Every picture below is the real output of the real notebook code, captured on a live workspace (run on 6 November 2026) and drawn as an image. They are renderings of text, not photos of the Databricks web page: our automation cannot sign in to the web UI (single sign-on), so the few steps that are clicks in the browser are described in words. Your workspace address and email are replaced by placeholders.

The big picture in 60 seconds

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E8F0FE','primaryTextColor':'#1F2937','primaryBorderColor':'#A8C0E8','lineColor':'#94A3B8','clusterBkg':'#F8FAFC','clusterBorder':'#CBD5E1'}}}%%
flowchart LR
    You["You<br/>in the browser"]:::blue --> NB["A notebook<br/>you run top to bottom"]:::yellow
    NB -->|"creates and controls"| SBX
    subgraph SBX["Temporary Linux machine (the sandbox)"]
        direction TB
        AG["Coding agent<br/>OpenCode"]:::purple --> TS["Tool server<br/>with the safety fence"]:::pink
    end
    AG -->|"thinks with"| GW["Databricks AI Gateway<br/>gpt-oss-120b"]:::green
    TS -->|"runs SQL, writes notebooks,<br/>only inside the fence"| WS["Your workspace<br/>tables, notebooks, jobs"]:::orange
    classDef blue fill:#E8F0FE,stroke:#A8C0E8,color:#1F2937
    classDef yellow fill:#FFF8E1,stroke:#F2D98D,color:#1F2937
    classDef purple fill:#EFE7FB,stroke:#C9B6EC,color:#1F2937
    classDef pink fill:#FDE7EF,stroke:#F2B5CB,color:#1F2937
    classDef green fill:#E6F4EA,stroke:#A8D5B5,color:#1F2937
    classDef orange fill:#FFEDE0,stroke:#F5C29C,color:#1F2937

Three ideas to hold on to:

  1. The sandbox is disposable. It is a temporary machine. When you delete it, its disk goes with it.
  2. The agent never touches your workspace directly. It asks the tool server, and the tool server enforces the rules. This matters because the agent runs without asking permission for each step.
  3. A supervisor makes the agent finish. The model we use can stop early. A small loop sends it back to work until it shows proof.

Before you start

You needHow to checkIf not
A Databricks workspace with serverless computeYou can attach a notebook to "Serverless"Ask your admin
Access to the AI Gateway sandbox service and the model gpt-oss-120bStep 2 below creates a sandbox without an errorAsk an admin to grant access to system.ai.sandbox
A personal access tokenStep 4 explains how to make oneUse a short lifetime (a day is plenty)
Somewhere the agent may writeA schema and a folder you do not mind filling with test objectsStep 5b creates nothing for you: pick or create them

The steps at a glance

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E8F0FE','primaryTextColor':'#1F2937','primaryBorderColor':'#A8C0E8','lineColor':'#94A3B8'}}}%%
flowchart LR
    S1["1 Import the<br/>notebook"]:::blue --> S2["2 Get a<br/>sandbox"]:::green --> S3["3 Copy the<br/>kit in"]:::yellow --> S4["4 Give it<br/>your token"]:::purple --> S5["5 Install<br/>the agent"]:::pink --> S5b["5b Start the<br/>fence"]:::orange --> S6["6 Ask a<br/>question"]:::teal --> S7["7 Build a<br/>notebook"]:::blue --> S8["8 Test the<br/>fence"]:::pink --> S9["9 Tidy up"]:::green
    classDef blue fill:#E8F0FE,stroke:#A8C0E8,color:#1F2937
    classDef green fill:#E6F4EA,stroke:#A8D5B5,color:#1F2937
    classDef yellow fill:#FFF8E1,stroke:#F2D98D,color:#1F2937
    classDef purple fill:#EFE7FB,stroke:#C9B6EC,color:#1F2937
    classDef pink fill:#FDE7EF,stroke:#F2B5CB,color:#1F2937
    classDef orange fill:#FFEDE0,stroke:#F5C29C,color:#1F2937
    classDef teal fill:#E0F5F3,stroke:#9AD5CE,color:#1F2937

Measured on our run (the two agent steps vary from run to run):

StepWhat happensTime we measured
2Sandbox created5 s
3Kit copied in4 s
4Token stored3 s
5Agent installed15 s
5bTool server started3 s
6First question51 s
7Build and run a notebook115 s
8Fence test35 s
Whole walk-throughunder 5 minutes of waiting

Step 1 · Import the notebook

The notebook is notebooks/launch_agent_from_notebook.py. It holds every command in this tutorial.

  1. In your workspace, open Workspace and go to your own folder.
  2. Choose Import (the menu on the folder, or the Add button). Upload the .py file, or paste its web address (the "raw" link on GitHub) if your import dialog offers a URL box.
  3. Open the imported notebook and attach it to Serverless compute.

The notebook needs only Python's standard library, so serverless is enough. Menu names may differ a little between workspaces.

Then run the first cell ("Step 1 · Helpers"). It only defines helper functions and prints nothing. The rest of the tutorial runs the notebook's cells one at a time, top to bottom.

Step 1

Step 2 · Get a sandbox

Run the "Step 2" cell. It asks Databricks for a temporary Linux machine and checks what is on it.

Step 2

What to look for: a sandbox id and the Databricks CLI version. The machine already has the Databricks command-line tool and Node. It does not have the coding agent yet.

Three facts about this machine:

Step 3 · Copy the kit into the sandbox

The "kit" is the small set of files from this repository that the agent needs: setup scripts, the rules file, the skills and the tool server. There are two ways to copy it. Use one.

Option A: copy from GitHubOption B: copy from a folder in your workspace
Howgit clone inside the sandboxput_tree(...) reads a Git folder under /Workspace
Good whenThe repository is public and already contains the kitYour copy is private or has your own changes
What we verifiedgit clone plus the whole flow below, on 6 Nov 2026the screenshots in this page

Step 3

Both options work. The screenshots below show Option B, because the kit was not on GitHub yet when we captured them. We then pushed it and re-ran the whole tutorial from a fresh sandbox with a plain git clone of Option A: install, fence, question, answer, all fine. If your copy is private, use Option B. put_tree never copies secrets: it skips .env, .git and caches, and it only takes the templates and mcp folders.

Step 4 · Give the agent your token

The agent needs a key to talk to Databricks. Make a personal access token:

  1. Click your profile picture, then Settings.
  2. Open Developer, then Access tokens, then Manage.
  3. Choose Generate new token, give it a short lifetime, and copy it.

Run the "Step 4" cell. A password-style box appears. Paste the token there.

Step 4

What happens to the token:

Not checked by us: the password box inside a real Databricks notebook (we ran the same code with the box answered automatically). If the box does not appear, store the token in a Databricks secret and read it with dbutils.secrets.get.

Safer than your own token: a token for a service principal that can only reach your scratch schema. We recommend it, but we did not test it. See 04 Safety.

Step 5 · Install the agent

Run the "Step 5" cell. It runs the kit's setup script in the sandbox.

Step 5

The script does five things, in this order:

#What it doesWhy it matters
1Installs OpenCode, the coding agentNeeds no root rights
2Makes a Python environment for the tool serverThe tool server is a small Python program
3Writes the agent's config filePoints it at the model, adds the tool server, hides its built-in file tools
4Copies the rules file (AGENTS.md) and skillsThe rules are the agent's working agreement
5Tests your tokenStops early if the sign-in is wrong

Two details in the config file are worth knowing about:

Step 5b · Start the tool server and set the fence

Edit the two names at the top of the "Step 5b" cell, then run it:

SCRATCH_SCHEMA = "workspace.agent_scratch"                    # the only schema the agent may write to
SCRATCH_FOLDER = "/Workspace/Users/you@example.com/agent_scratch"   # the only folder the agent may write to

Create the schema and the folder first if they do not exist (CREATE SCHEMA workspace.agent_scratch in a SQL cell; a new folder in the Workspace browser).

Step 5b

The screenshot's three lines are the fence. They are enforced by the tool server, not by the agent. The agent could be confused or tricked, and the fence would still hold. Step 8 proves it.

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E8F0FE','primaryTextColor':'#1F2937','primaryBorderColor':'#A8C0E8','lineColor':'#94A3B8'}}}%%
flowchart LR
    A["Agent asks:<br/>write something"]:::purple --> T{"Tool server<br/>checks the target"}:::pink
    T -->|"inside the schema,<br/>folder or job-name prefix"| OK["Allowed:<br/>it happens"]:::green
    T -->|"anywhere else"| NO["Refused with a clear<br/>message the agent can read"]:::orange
    R["Reading anything<br/>you can read"]:::blue --> OK2["Always allowed"]:::green
    classDef purple fill:#EFE7FB,stroke:#C9B6EC,color:#1F2937
    classDef pink fill:#FDE7EF,stroke:#F2B5CB,color:#1F2937
    classDef green fill:#E6F4EA,stroke:#A8D5B5,color:#1F2937
    classDef orange fill:#FFEDE0,stroke:#F5C29C,color:#1F2937
    classDef blue fill:#E8F0FE,stroke:#A8C0E8,color:#1F2937

Step 6 · Ask your first question

Run the "Step 6" cell. The request is a read-only data question:

Which three pickup zip codes in samples.nyctaxi.trips have the highest total fare_amount? Show the SQL you ran and the numbers.

Step 6

How to read the output, from top to bottom:

What you seeWhat it means
supervisor: empty final answer, continuing (1)The model stopped without answering, and the supervisor sent it back to work. This is normal for this model: it happened on 3 of our 6 asks over two runs.
supervisor: audit pass 1 and 2The supervisor asks: "name the tool call that proves each requirement". This is what turns a confident claim into checked work.
=== FINAL ANSWER ===The agent's report, in four fixed headings: Done, Evidence, Assumptions and unverified, Anything odd or suspicious.
--- the agent made 2 tool callsIt looked at the table's columns, then ran the SQL.

Do not trust, check. Run the SQL yourself in a SQL cell and compare. On our run it returned 11422 → 19209.5, 11371 → 14798.84, 10001 → 13028.01, exactly what the agent reported.

Step 7 · Ask for something real: build a notebook and prove it works

Run the "Step 7" cell. The request:

Create a notebook taxi_hours in the scratch folder: a title, then cells that count trips and total fare by pickup hour, chart total fare by hour, and end with dbutils.notebook.exit(<number of hours covered>). Run it. Fix any error. Tell me the exit value.

Step 7

This is the work Genie Code is usually asked for. The report's evidence table says what was done and what proved it:

Open the new notebook in your scratch folder and look at it. Then run the check below.

Do not trust, check. In a SQL cell:

SELECT count(DISTINCT hour(tpep_pickup_datetime)) FROM samples.nyctaxi.trips   -- we got 24

On our run this matched the agent's exit value, and the notebook listed in the folder was taxi_hours.

The word invalid sometimes appears in the list of tool calls. It means the model sent a malformed call that was rejected. A few are harmless; many in one task mean the model is struggling.

Step 8 · Test the fence

Run the "Step 8" cell. The request deliberately asks for something outside the fence:

Create a table workspace.default.not_allowed_demo with one row, then tell me exactly what happened.

Step 8

The agent tried. The tool server refused with write blocked: target workspace.default.not_allowed_demo is not inside allowed schemas ['workspace.agent_scratch'], and the agent reported that honestly. We confirmed afterwards that the table does not exist.

This is the most important screenshot in the tutorial. It shows that the safety does not depend on the model behaving well.

Where the fence has a hole. It covers the tool server's tools. The Databricks command-line tool in the same sandbox is not fenced: it acts with your token's full power. Rules that say "do not" are only words. Use a restricted token if the agent will ever run unattended (04 Safety).

Step 9 · Tidy up

Run the "Step 9" cell. It stops the tool server and deletes the sandbox.

Step 9

The sandbox and its disk are gone. What the agent created in your workspace stays: delete the taxi_hours notebook, and drop the scratch schema, when you are done.


Part 2 · The same thing from a real shell

Everything above is a notebook cell calling a shell. This part shows the shell itself, because once the sandbox is up, a terminal is the fastest way to work: one command installs, one starts the fence, one asks a question.

We captured this session on a fresh sandbox (run on 6 November 2026). It took about a minute in total. The commands are exactly what the notebooks run, so nothing new is installed.

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E8F0FE','primaryTextColor':'#1F2937','primaryBorderColor':'#A8C0E8','lineColor':'#94A3B8'}}}%%
flowchart LR
    A["1 look around"]:::blue --> B["2 install"]:::green --> C["3 start the fence"]:::pink --> D["4 see the tools"]:::yellow --> E["5 ask"]:::purple --> F["6 read the log"]:::teal --> G["7 use the CLI"]:::orange
    classDef blue fill:#E8F0FE,stroke:#A8C0E8,color:#1F2937
    classDef green fill:#E6F4EA,stroke:#A8D5B5,color:#1F2937
    classDef pink fill:#FDE7EF,stroke:#F2B5CB,color:#1F2937
    classDef yellow fill:#FFF8E1,stroke:#F2D98D,color:#1F2937
    classDef purple fill:#EFE7FB,stroke:#C9B6EC,color:#1F2937
    classDef teal fill:#E0F5F3,stroke:#9AD5CE,color:#1F2937
    classDef orange fill:#FFEDE0,stroke:#F5C29C,color:#1F2937

How to get this shell without a local terminal. Fill a notebook cell with your command: print(sh(sandbox_id, "your command here")). That runs it in the sandbox and prints what came back. The notebooks/launch_agent_from_notebook.py helper sh() is all you need. If your workspace offers the web terminal, the same commands should work there, but we have not verified that route.

1 · Look around before installing anything

uname -sm; databricks --version; node --version; command -v opencode || echo 'opencode: not installed yet'

Shell: what is on the machine

The machine runs Linux, and Databricks' own command-line tool (version 1.23.0) and Node are already there. The coding agent is not: that is the only thing we add, in your own folder, without administrator rights.

2 · Install the agent and the rules

export DATABRICKS_HOST="https://YOUR-WORKSPACE.cloud.databricks.com"
cd ~/edgegenie && bash templates/setup_agent.sh

Shell: install the agent

Five short steps: install the agent, create a Python environment for the tool server, write the agent's config, copy the rules and skills, and prove the token works (signed in as ...). If the token is wrong, it stops here rather than letting the agent fail later.

3 · Start the fence

cd ~/agent-work && bash start_mcp.sh workspace.agent_scratch /Workspace/Users/you/agent_scratch

Shell: start the tool server

The three lines it prints are the fence: the only schema, the only folder, and the prefix for any job it creates.

4 · See the tools the agent actually has

python -c '... list tools from http://127.0.0.1:8765/mcp ...'

Shell: the tools

Nineteen tools, each doing one Databricks thing. This is the agent's whole world: it cannot invent a different way to reach your workspace. That is why the fence holds, and why the agent does not need to remember command-line flags.

5 · Ask a question

bash ask.sh "How many trips are in samples.nyctaxi.trips, and over what date range?"

Shell: ask a question

It took about 30 seconds. Two audit passes ran, then the report. Note the third evidence row: the agent checked its SQL result against the table's own metadata (numRows: 21932, matching the count) instead of trusting one query.

Do not trust, check. The same numbers from our own SQL: 21,932 trips, from 2016-01-01 00:04:30 to 2016-02-29 23:51:20.

6 · Read the log of every step

python3 - <<'PY'
import json
for line in open("events.jsonl"):
    e = json.loads(line)
    if e.get("type") == "tool_use":
        p, st = e["part"], e["part"].get("state", {})
        print(f"{p['tool']:<24} {st.get('status',''):<10} {json.dumps(st.get('input',{}))[:70]}")
PY

Shell: the event log

Every message and tool call is one line in ~/agent-work/events.jsonl. When a report surprises you, this file says what really happened. Treat it as private: the agent is told never to print your token, and we found no token in ours.

7 · The same shell can use the Databricks CLI directly

databricks current-user me
databricks workspace list /Users/you

Shell: the Databricks CLI

This is not the agent; it is you, using the tool Databricks preinstalls. It matters for two reasons:

The commands you will use most

You want toRun in the sandbox
Ask the agent somethingcd ~/agent-work && bash ask.sh "your request"
Run a long tasknohup bash ask.sh "..." > run.log 2>&1 & then tail -f run.log (a single call is cut after about 180 s)
Change where it may writebash start_mcp.sh <catalog.schema> </Workspace/Users/you/folder>
Stop the tool serverbash start_mcp.sh stop
See every step it tookevents.jsonl in ~/agent-work
Check who you are signed in asdatabricks current-user me

Make it yours

I want to...Change this
Let it write somewhere elseThe two names in Step 5b (and restart the tool server)
Teach it my team's rulesEdit ~/agent-work/AGENTS.md; plain English works best
Add my own how-to notesPut a .md file in ~/agent-work/skills/ and mention it in the rules
Use a stronger modelGemini 3.8 Flash scored higher in our exams: see 02 Setup, step 4
Use GitHub Copilot insteadSee 02 Setup, step 9 and 06
Add Databricks' official skills and CLIThe hybrid setup ("V6") in 03 Toolbox

When something goes wrong

What you seeWhat it meansWhat to do
DATABRICKS_HOST: set DATABRICKS_HOSTThe host variable was not passed into the shellUse the notebook's helpers (they pass it); in your own commands add export DATABRICKS_HOST=... first
no DEFAULT profile configured from the CLIThe sandbox points the CLI at an empty settings fileunset DATABRICKS_CONFIG_FILE DATABRICKS_CONFIG_PROFILE (our scripts already do)
could not sign in in Step 5Wrong token, expired token, or wrong hostMake a new token and rerun Step 4
A spinner and no answerThe model's output limit is too highKeep "output": 24000 in opencode.json
write blocked: ... not inside allowed schemasThe fence workedName a path inside the fence, or restart the tool server with a different fence
The notebook cell stops after ~3 minutesOne call's time limitUse ask(), which polls
Output says supervisor: empty final answer several timesThe model keeps stallingNormal up to a point. If every task needs it, try a stronger model
406 Not Acceptable in mcp.logOur start-up check knocked on the tool server's doorIgnore it
The agent hands you code instead of doing the workThe rules file is missing or ignoredCheck that ~/agent-work/AGENTS.md exists and you ran the agent from that folder

What this tutorial does not prove

Where to go next

If you want to...Read
Understand why this works01 Big picture
See the other ways to set it up02 Setup reference
Know what is safe and what is not04 Safety
See the evidence for how good it is06 Results
Decide what to deploy07 Decision guide