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
Install Dependencies
Install the OpenAI SDK and HatiData agent SDK.
pip install openai hatidata-agent
hati initHatiData initialized successfully.
Proxy running on localhost:5439Note: Branches use schema-based isolation — each branch gets its own schema namespace.
Set Up Baseline Data
Create a portfolio table in the main state that the agent will use for exploration.
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']}")Baseline portfolio:
AAPL: 100 shares @ $185.0
GOOGL: 50 shares @ $175.0
MSFT: 75 shares @ $420.0Create Exploration Branches
Create isolated branches for the agent to explore different investment scenarios.
# 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")Created branches: aggressive-growth, conservative-hedge
Branch writes complete — main state is untouchedNote: Branches use copy-on-write: reads are zero-copy views, writes materialize only the modified tables.
Compare Branch Results
Query each branch to compare the portfolio outcomes before deciding which to merge.
# 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)")=== 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)Merge or Discard
Merge the winning branch back to main state and discard the other.
# 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']}")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.0Note: Merge strategies: branch_wins, main_wins, manual, abort. Use branch_wins when you want the branch to overwrite main.