← All Cookbooks
OpenAIAdvanced30 min

OpenAI Agents + HatiData: Branch-Based Exploration

Use HatiData's branch isolation to let OpenAI agents explore hypothetical scenarios without affecting the main data state. Merge successful outcomes back.

What You'll Build

An OpenAI agent that explores hypothetical scenarios in isolated branches, then merges successful outcomes back to main state.

Prerequisites

$pip install openai hatidata-agent

$hati init

$OpenAI API key

Architecture

┌──────────────┐    ┌──────────────┐
│  OpenAI      │───▶│  HatiData    │
│  Agent       │    │  Branching   │
└──────────────┘    └──────┬───────┘
                           │
              ┌────────────┼────────────┐
              ▼            ▼            ▼
         ┌────────┐  ┌────────┐  ┌────────┐
         │ Main   │  │Branch A│  │Branch B│
         │ State  │  │(schema)│  │(schema)│
         └────────┘  └────────┘  └────────┘

Key Concepts

  • Schema-based isolation: each branch gets its own isolated schema, providing full read/write isolation from main state
  • Copy-on-write: branches start as zero-copy views of main state and only materialize tables on first write
  • Merge strategies: branch_wins (overwrite main), main_wins (keep main), manual (row-level conflict resolution), abort (cancel if conflicts)
  • Parallel exploration: agents can create multiple branches simultaneously to evaluate competing strategies
  • Garbage collection: discarded branches are automatically cleaned up by the branch garbage collector

Step-by-Step Implementation

1

Install Dependencies

Install the OpenAI SDK and HatiData agent SDK.

Bash
pip install openai hatidata-agent
hati init
Expected Output
HatiData initialized successfully.
Proxy running on localhost:5439

Note: Branches use schema-based isolation — each branch gets its own schema namespace.

2

Set Up Baseline Data

Create a portfolio table in the main state that the agent will use for exploration.

Python
from hatidata_agent import HatiDataAgent

hati = HatiDataAgent(host="localhost", port=5439, agent_id="portfolio-agent")

# Create baseline portfolio
hati.execute("""
    CREATE TABLE portfolio (
        ticker VARCHAR, shares INTEGER,
        avg_cost DOUBLE, current_price DOUBLE
    )
""")

hati.execute("""
    INSERT INTO portfolio VALUES
        ('AAPL', 100, 150.0, 185.0),
        ('GOOGL', 50, 120.0, 175.0),
        ('MSFT', 75, 310.0, 420.0)
""")

result = hati.query("SELECT ticker, shares, current_price FROM portfolio")
print("Baseline portfolio:")
for r in result:
    print(f"  {r['ticker']}: {r['shares']} shares @ ${r['current_price']}")
Expected Output
Baseline portfolio:
  AAPL: 100 shares @ $185.0
  GOOGL: 50 shares @ $175.0
  MSFT: 75 shares @ $420.0
3

Create Exploration Branches

Create isolated branches for the agent to explore different investment scenarios.

Python
# Create two branches for parallel exploration
hati.execute("SELECT branch_create('aggressive-growth')")
hati.execute("SELECT branch_create('conservative-hedge')")

print("Created branches: aggressive-growth, conservative-hedge")

# In the aggressive branch: buy more tech
hati.execute("""
    SELECT branch_query(
        'aggressive-growth',
        'INSERT INTO portfolio VALUES (''NVDA'', 200, 800.0, 950.0)'
    )
""")

hati.execute("""
    SELECT branch_query(
        'aggressive-growth',
        'UPDATE portfolio SET shares = 200 WHERE ticker = ''AAPL'''
    )
""")

# In the conservative branch: diversify into bonds
hati.execute("""
    SELECT branch_query(
        'conservative-hedge',
        'INSERT INTO portfolio VALUES (''BND'', 500, 72.0, 74.0)'
    )
""")

print("Branch writes complete — main state is untouched")
Expected Output
Created branches: aggressive-growth, conservative-hedge
Branch writes complete — main state is untouched

Note: Branches use copy-on-write: reads are zero-copy views, writes materialize only the modified tables.

4

Compare Branch Results

Query each branch to compare the portfolio outcomes before deciding which to merge.

Python
# Compare portfolios across branches
for branch in ['aggressive-growth', 'conservative-hedge']:
    result = hati.query(f"""
        SELECT branch_query(
            '{branch}',
            'SELECT ticker, shares, current_price, shares * current_price AS value FROM portfolio'
        )
    """)
    total = sum(float(r['value']) for r in result)
    print(f"\n=== {branch} ===")
    for r in result:
        print(f"  {r['ticker']}: {r['shares']} shares, value=${float(r['value']):,.0f}")
    print(f"  Total portfolio value: ${total:,.0f}")

# Check main state is unchanged
main_result = hati.query("SELECT COUNT(*) AS cnt FROM portfolio")
print(f"\nMain state: {main_result[0]['cnt']} positions (unchanged)")
Expected Output
=== aggressive-growth ===
  AAPL: 200 shares, value=$37,000
  GOOGL: 50 shares, value=$8,750
  MSFT: 75 shares, value=$31,500
  NVDA: 200 shares, value=$190,000
  Total portfolio value: $267,250

=== conservative-hedge ===
  AAPL: 100 shares, value=$18,500
  GOOGL: 50 shares, value=$8,750
  MSFT: 75 shares, value=$31,500
  BND: 500 shares, value=$37,000
  Total portfolio value: $95,750

Main state: 3 positions (unchanged)
5

Merge or Discard

Merge the winning branch back to main state and discard the other.

Python
# Merge the aggressive branch (higher returns)
hati.execute("SELECT branch_merge('aggressive-growth', 'branch_wins')")
print("Merged aggressive-growth into main state")

# Discard the conservative branch
hati.execute("SELECT branch_discard('conservative-hedge')")
print("Discarded conservative-hedge branch")

# Verify main state updated
result = hati.query("SELECT ticker, shares, current_price FROM portfolio ORDER BY ticker")
print("\nFinal portfolio (main state):")
for r in result:
    print(f"  {r['ticker']}: {r['shares']} shares @ ${r['current_price']}")
Expected Output
Merged aggressive-growth into main state
Discarded conservative-hedge branch

Final portfolio (main state):
  AAPL: 200 shares @ $185.0
  GOOGL: 50 shares @ $175.0
  MSFT: 75 shares @ $420.0
  NVDA: 200 shares @ $950.0

Note: Merge strategies: branch_wins, main_wins, manual, abort. Use branch_wins when you want the branch to overwrite main.

Ready to build?

Install HatiData locally and start building with OpenAI in minutes.

Join Waitlist