Plug & Play

Build a full Jazzmine market agent in one Python file — inline tools, intent flows, sandboxed execution, interactive CLI, and optional HTTP server mode.

Set up once, build one Python file, then choose one run path: interactive CLI or HTTP server mode.

Example information

This is a complete working example. You can find the full source in the examples directory on GitHub.

Prerequisites: Docker running locally, and a Mistral API key.

1. Setup once

install.sh
pip install jazzmine
pip install yfinance==0.2.66 pandas==2.2.3 numpy==2.1.3
env.sh
export MISTRAL_API_KEY="your-key"
export MISTRAL_BASE_URL="https://api.mistral.ai"
export MISTRAL_MODEL="mistral-medium-latest"

If you will run HTTP mode, set host and port:

server_env.sh
export JAZZMINE_SERVER_HOST="127.0.0.1"
export JAZZMINE_SERVER_PORT="8010"

2. Build quickstart_market_full.py in this order

Copy each block into the same Python file in the order below.

2.1 Shared imports and constants

quickstart_market_full.py
from __future__ import annotations

import asyncio
import os
from uuid import uuid4

from jazzmine.core import (
    AgentBuilder,
    Flow,
    JsonStorage,
    OpenAILLMConfig,
    ServerConfig,
    ToolParameter,
    ToolResponse,
    tool,
)

SANDBOX_NAME = "market"

YAHOO_ALLOWLIST_HOSTS = [
    "query1.finance.yahoo.com",
    "query2.finance.yahoo.com",
    "finance.yahoo.com",
]

TOOL_DEPS = ["yfinance==0.2.66", "pandas==2.2.3", "numpy==2.1.3"]

2.2 Tools

Implement executable actions that fetch live market data and return structured results.

quickstart_market_full.py
@tool(
    description="Fetch a quick market snapshot for one ticker.",
    parameters=[
        ToolParameter("ticker", "str", "Ticker symbol like AAPL.", required=True),
        ToolParameter("period", "str", "5d, 1mo, 3mo, 6mo, 1y", required=False, default="1mo"),
    ],
    dependencies=TOOL_DEPS,
    sandbox=SANDBOX_NAME,
)
async def fetch_market_snapshot(ticker: str, period: str = "1mo") -> ToolResponse:
    import pandas as pd
    import yfinance as yf

    symbol = ticker.strip().upper()
    if not symbol:
        return ToolResponse(success=False, message="ticker cannot be empty")

    history = yf.Ticker(symbol).history(period=period, interval="1d")
    if history is None or history.empty:
        return ToolResponse(success=False, message=f"No data returned for {symbol}")

    latest = history.iloc[-1]
    close = float(latest["Close"])
    return ToolResponse(success=True, data={"ticker": symbol, "period": period, "close": close})

2.3 Flows

Map user intent patterns to tools so requests route predictably to the right behavior.

quickstart_market_full.py
def build_flows() -> list[Flow]:
    return [
        Flow(
            name="market_snapshot",
            description="Fetch latest market snapshot for one ticker.",
            condition="User asks for latest price, move, OHLC, quote, or quick market view.",
            desired_effects=[
                "Call snapshot tool for the requested ticker.",
                "Report close and period clearly.",
            ],
            examples=["Give me a quick snapshot for AAPL", "What is the latest price of TSLA?"],
            tools=["fetch_market_snapshot"],
            priority=(1, 0),
        ),
    ]

2.4 Agent builder and sandbox config

Configure model, storage, sandbox execution policy, and attach the flow graph once.

quickstart_market_full.py
def build_base_agent_builder() -> AgentBuilder:
    api_key = os.environ["MISTRAL_API_KEY"]
    base_url = os.environ.get("MISTRAL_BASE_URL", "https://api.mistral.ai")
    model = os.environ.get("MISTRAL_MODEL", "mistral-medium-latest")

    return (
        AgentBuilder(
            name="MarketLite",
            agent_id="market-lite-v1",
            personality="You are a concise market assistant. Use tools for live numbers.",
        )
        .llm(OpenAILLMConfig(model=model, api_key=api_key, base_url=base_url, temperature=0.2))
        .storage(JsonStorage(path="./market_lite_store.json"))
        .sandbox(
            name=SANDBOX_NAME,
            python_version="3.11",
            timeout_sec=60,
            allowed_hosts=YAHOO_ALLOWLIST_HOSTS,
            pip_packages=TOOL_DEPS,
        )
        .flows(build_flows())
        .version("1.0.0")
    )

2.5 Interactive CLI loop function

quickstart_market_full.py
async def run_interactive() -> None:
    agent, teardown = await build_base_agent_builder().build()
    conversation_id = f"market-lite-{uuid4().hex[:8]}"
    try:
        while True:
            user_input = input("\nYou: ").strip()
            if user_input.lower() in {"/quit", "quit", "exit", "q"}:
                break
            result = await agent.chat(
                user_id="market-user", conversation_id=conversation_id, content=user_input
            )
            print("\nMarketLite:", result.response)
    finally:
        await teardown()

2.6 HTTP server function

quickstart_market_full.py
async def run_http_server() -> None:
    host = os.environ.get("JAZZMINE_SERVER_HOST", "127.0.0.1")
    port = int(os.environ.get("JAZZMINE_SERVER_PORT", "8010"))
    _agent, teardown = await build_base_agent_builder().server(ServerConfig(host=host, port=port)).build()
    print("MarketLite server is running")
    stop_event = asyncio.Event()
    try:
        await stop_event.wait()
    finally:
        await teardown()

2.7 Main entrypoint and mode switch

quickstart_market_full.py
async def main() -> None:
    mode = os.environ.get("MARKET_RUN_MODE", "loop").strip().lower()
    if mode in {"server", "http"}:
        await run_http_server()
    else:
        await run_interactive()


if __name__ == "__main__":
    asyncio.run(main())

3. Path A: Run interactive CLI mode

Loop mode is the default because main runs run_interactive when MARKET_RUN_MODE is not set.

run_loop.sh
export MISTRAL_API_KEY="your-key"
python3 quickstart_market_full.py

4. Path B: Run HTTP server mode

run_server.sh
export MISTRAL_API_KEY="your-key"
export MARKET_RUN_MODE="server"
python3 quickstart_market_full.py

Use the chat endpoint printed at startup:

request.sh
CHAT_ENDPOINT="http://127.0.0.1:8010/<chat_endpoint_from_startup>"

curl -X POST "$CHAT_ENDPOINT" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "market-user", "conversation_id": "market-demo-1", "content": "Compare AAPL, MSFT, NVDA over 6mo."}'

5. Frontend integration for HTTP mode

frontend_install.sh
npm install @jazzmine-ui/react @jazzmine-ui/sdk
client.tsx
import { JazzmineChat } from "@jazzmine-ui/react";
import "@jazzmine-ui/react/styles";
import { JazzmineClient } from "@jazzmine-ui/sdk";

const client = new JazzmineClient("http://127.0.0.1:8010");

export default function JazzmineTestPage() {
  return <JazzmineChat client={client} />;
}

On this page