ANTIGRAVITY LABJP
Articles/Editor View
Editor View/2026-04-21Intermediate

Three Practical Workflows for Pairing Antigravity with Jupyter

Three concrete workflows for combining Antigravity's agent-driven development with Jupyter's exploratory feel. Covers cell-level editing, passing execution results to the agent, and writing an AGENTS.md tuned for data analysis.

antigravity435jupyterpython26data-scienceworkflow50

If you write Python in Antigravity, you have probably felt a quiet pull: the analysis part wants to live in Jupyter, but the productivity gains from the agent pull everything else toward Antigravity's editor, and before you know it the notebook sits unused. I spent a stretch caught in exactly that pendulum while working on a personal analytics project. Lean too hard on Antigravity and I lost the tactile feel of exploratory work; lean too hard on Jupyter and nothing ever crystallised into reusable modules.

This post shares three workflows I now use to stop that pendulum. It is not a "how to open a notebook in Antigravity" guide. It focuses on how to split the work between the agent and hands-on exploration, with rules and code you can adopt today.

Workflow 1 — Grow a Notebook Into a .py Module

When I start an analysis, I give myself a rule: the first 30 to 60 minutes are Jupyter-only. No agent calls, no generation. I write cells by hand, run df.head() several times, and let the shape of the data sink in. Skipping this step and letting the agent take over too early tends to produce code that works on the surface but misses the quirks of the actual data.

Once the exploration settles, I bring the agent in for modularisation. A concrete example:

# From notebooks/eda_sales_2026q1.ipynb
# Cell 3: monthly summary logic
import pandas as pd
 
def summarize_monthly(df: pd.DataFrame, value_col: str = "amount") -> pd.DataFrame:
    """Return monthly totals, counts, and average ticket size.
 
    The intent is to move this to src/analytics/sales.py after extracting it
    in Antigravity.
    """
    monthly = (
        df.assign(month=df["date"].dt.to_period("M"))
        .groupby("month")
        .agg(total=(value_col, "sum"), count=(value_col, "count"))
    )
    monthly["avg_ticket"] = monthly["total"] / monthly["count"]
    return monthly.reset_index()
 
# Expected output: a DataFrame with month / total / count / avg_ticket
summarize_monthly(df).head()

With that cell selected, I ask the agent something like:

"Move this cell into src/analytics/sales.py, add type hints, and write a single pytest case for it. In the notebook, replace the cell with from analytics.sales import summarize_monthly."

The trick is to keep the cell selected when making the request. Antigravity prioritises the active selection as context, so you rarely need to spell out which cell you mean. I regularly turn a notebook with ten or so exploratory cells into a clean .py module in half a day using this pattern.

One habit that matters: do not leave the empty shell of a migrated cell behind. I add a magic comment like # moved-to: analytics.sales.summarize_monthly to migrated cells and make it a morning routine to delete them. Otherwise exploratory notebooks balloon forever.

Workflow 2 — Have the Agent Rewrite Cells One at a Time

The second workflow flips the direction. Instead of moving notebook code out, I ask the agent to write or rewrite a single cell while I stay in the notebook. Letting the agent generate an entire notebook tends to erase the traces of exploration, but cell-level collaboration preserves them.

The pattern I use: put the intent at the top of the cell as a comment, then use that comment as the prompt.

# TODO(agent): Use statsmodels.tsa.seasonal.STL to decompose the past 12 months of
#              sales into seasonal / trend / residual components. Return a DataFrame
#              with columns season / trend / resid. Assume period=12.
#              Also print the standard deviation of the residual.
 
import pandas as pd
from statsmodels.tsa.seasonal import STL
 
def decompose(series: pd.Series) -> pd.DataFrame:
    stl = STL(series, period=12, robust=True).fit()
    result = pd.DataFrame({
        "season": stl.seasonal,
        "trend": stl.trend,
        "resid": stl.resid,
    })
    print(f"resid std: {result['resid'].std():.3f}")
    return result
 
# Expected output: one line with "resid std: ..." plus a 3-column DataFrame
decomposed = decompose(df.set_index("date")["amount"])
decomposed.tail()

The nice side effect of this style is that when you revisit the notebook later, it is immediately obvious which cells were agent-written. A quick grep "# TODO(agent):" surfaces every generated block, which helps a lot during code review and verification.

One warning: Antigravity's agent often overlooks Jupyter magic commands such as %timeit or %load_ext. If you ask it to rewrite a performance-measurement cell, be explicit: "keep the %%time line." I lost a few measurement lines early on and spent longer than I would like figuring out why numbers looked off.

Workflow 3 — Feed Execution Results Into the Agent's Context

The third workflow is where the biggest productivity gains live. Instead of asking the agent to reason about data in the abstract, you show it the result of a quick cell and let it make decisions from there.

Correlation matrices are a great example:

# Compute correlation, then feed the text to the agent
corr = df[["age", "income", "score", "ltv"]].corr().round(2)
print(corr)
 
# Example output:
#          age  income  score   ltv
# age     1.00    0.12   0.08  0.31
# income  0.12    1.00   0.45  0.67
# score   0.08    0.45   1.00  0.58
# ltv     0.31    0.67   0.58  1.00

Copy that printed matrix into the agent chat and say: "Write a linear regression model with ltv as the target. Here is the correlation matrix." The agent will typically suggest income and score as features because it can read the numbers directly. The important bit is to pass the matrix as text rather than as a screenshot.

I deliberately avoid sending plot images to the agent when the decision is a statistical one. Antigravity's multimodal capabilities have improved, but numeric tables are still more reliable than charts for quantitative reasoning. Getting into the habit of sharing describe(), value_counts(), and corr() output as text noticeably accelerates model selection.

Writing an AGENTS.md That Fits Data Analysis

To keep these three workflows consistent across sessions, I keep a data-analysis-oriented AGENTS.md at the project root. Antigravity reads this on startup, and the following kinds of rules have repeatedly saved me from small disasters.

# Data Analysis Project — Agent Guidelines
 
## Notebook Policy
- Notebooks under `notebooks/` are for exploration only. Final logic must live in `src/analytics/`.
- When editing existing notebook cells, only touch cells that start with `# TODO(agent):`.
- Never remove magic commands (`%%time`, `%matplotlib inline`, etc.) without being asked.
 
## Data Handling
- Never write into `data/raw/`. Processed outputs belong under `data/interim/`.
- Hash columns containing PII (`email`, `phone`, `address`) before any aggregation.
- Every function that returns a DataFrame must have a docstring describing the expected columns.
 
## Testing
- Any function placed in `src/analytics/` requires a pytest test.
- Minimal fixture CSVs go under `tests/fixtures/`.
- Use `pandas.testing.assert_frame_equal` so both types and values are verified.

This file also works for other agents, so if your team mixes Antigravity with Claude Code or similar tools, the same rules apply everywhere. For a deeper look at writing this kind of guideline, I wrote A Practical Guide to AGENTS.md.

A Trade-off Worth Acknowledging

When you run all three workflows, the hardest question is always the same: when do you leave code in the notebook, and when do you promote it to a module? There is no universal answer.

A rule of thumb that has served me well: the moment you notice you have copy-pasted the same cell three times, it is time to modularise. Data analysis sits between "throwaway" and "reusable" by nature, and you need a feel for when to cross the line. The agent, usefully, makes a decent second opinion. Asking "should this cell be a function, or is it fine to leave as is?" often produces a sensible take.

For editor-side customisations that complement these workflows, I cover more ground in Advanced Customisation Guide for the Antigravity Editor. Pairing that with the notebook practices here gives you a fairly complete Python analysis setup.

One Thing To Try Tomorrow

Open one of your current analysis notebooks and look for a single function you have copy-pasted three or more times. When you find one, select that cell and ask the Antigravity agent to "move this into a new file under src/analytics/ and write one minimal test." That is Workflow 1 in miniature, and it is enough to start feeling where the agent ends and where your own exploration belongs.

Migrate one small function at a time, and the role split between Jupyter and the agent starts to feel natural. The pendulum quiets down once you have walked the loop a few times yourself.

Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Editor View2026-06-15
Supervising Multiple Agents at Once on the Antigravity 2.0 Desktop: Screen Layout and Interruption Design
Now that Antigravity 2.0 has been recast as an agent control tower, here is how I lay out the screen, decide when to interrupt, and surface state when running several agents in parallel.
Editor View2026-05-09
Splitting AI Context Across Multiple Repos with Antigravity Multi-root Workspaces
When you open multiple similar repos in a single Antigravity window, the AI sometimes pulls conventions from the wrong project. Here is how I split AI context per folder using .antigravity/rules, learned from running four near-identical Next.js sites side by side.
Editor View2026-05-07
Fixing 'Find References' in Antigravity When Results Are Empty or Incomplete
When Find References returns nothing or only some of the call sites in Antigravity, the cause depends on whether the language server or the workspace index is silent. This guide walks through the diagnosis for TypeScript, Python, and monorepo setups.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →