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
pip install jazzmine
pip install yfinance==0.2.66 pandas==2.2.3 numpy==2.1.3export 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:
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
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.
@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.
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.
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
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
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
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.
export MISTRAL_API_KEY="your-key"
python3 quickstart_market_full.py4. Path B: Run HTTP server mode
export MISTRAL_API_KEY="your-key"
export MARKET_RUN_MODE="server"
python3 quickstart_market_full.pyUse the chat endpoint printed at startup:
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
npm install @jazzmine-ui/react @jazzmine-ui/sdkimport { 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} />;
}