DEV Community

shashank ms
shashank ms

Posted on

Understanding Agentic Workload for LLM with Oxlo

We are building a stock briefing agent that takes a list of ticker symbols, fetches live price data through a Python tool, and returns a concise market summary. This is a practical template for anyone automating research workflows or monitoring portfolios with LLMs. Because the agent runs multiple tool calls inside a single conversation loop, context length grows quickly, which is where Oxlo.ai's request-based pricing becomes useful compared to token-based billing. You can explore the predictable costs at https://oxlo.ai/pricing.

What you'll need

  • Python 3.10 or newer
  • The OpenAI SDK and yfinance: pip install openai yfinance
  • An Oxlo.ai API key from https://portal.oxlo.ai

1. Bootstrap the Oxlo.ai client

I always start by verifying the endpoint with a simple ping. This confirms that my API key and the Oxlo.ai base URL are wired correctly.

from openai import OpenAI

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")

response = client.chat.completions.create(
    model="qwen-3-32b",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Say hello and confirm you are ready."},
    ],
)
print(response.choices[0].message.content)

2. Define the system prompt and tool schema

The agent needs a clear directive and a structured tool it can call. I keep the system prompt explicit about output format and step order.

SYSTEM_PROMPT = """You are a financial briefing agent. Your job is to:
1. Accept a list of stock ticker symbols.
2. Call the get_stock_snapshot tool for each ticker.
3. Wait for the results.
4. Write a concise markdown briefing with current price, daily change, and a one-sentence outlook per ticker.
Only call the tool once per ticker. Do not invent data."""
TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "get_stock_snapshot",
            "description": "Fetch the current stock price and daily change percent for a given ticker.",
            "parameters": {
                "type": "object",
                "properties": {
                    "ticker": {
                        "type": "string",
                        "description": "Stock ticker symbol, e.g. AAPL"
                    }
                },
                "required": ["ticker"]
            }
        }
    }
]

3. Implement the data fetcher

The tool itself uses yfinance to pull the last two closing prices so we can calculate a daily change. Keeping this deterministic prevents the LLM from hallucinating numbers.

import yfinance as yf
import json

def get_stock_snapshot(ticker: str):
    stock = yf.Ticker(ticker)
    hist = stock.history(period="2d")
    if hist.empty:
        return {"ticker": ticker, "error": "No data found."}
    current = hist["Close"].iloc[-1]
    previous = hist["Close"].iloc[-2]
    change_pct = round(((current - previous) / previous) * 100, 2)
    return {
        "ticker": ticker,
        "price": round(current, 2),
        "change_percent": change_pct
    }

4. Wire the agent loop

Now I connect the LLM to the tool. The loop sends the conversation to Oxlo.ai, checks for a tool_calls payload, executes any requested functions, and appends the results back to the context window.

def run_agent(tickers):
    messages = [
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": f"Provide a briefing for: {', '.join(tickers)}."},
    ]

    while True:
        response = client.chat.completions.create(
            model="qwen-3-32b",
            messages=messages,
            tools=TOOLS,
            tool_choice="auto",
        )
        message = response.choices[0].message

        if message.tool_calls:
            messages.append({
                "role": "assistant",
                "content": message.content or "",
                "tool_calls": [tc.model_dump() for tc in message.tool_calls]
            })

            for tc in message.tool_calls:
                if tc.function.name == "get_stock_snapshot":
                    args = json.loads(tc.function.arguments)
                    result = get_stock_snapshot(args["ticker"])
                    messages.append({
                        "role": "tool",
                        "tool_call_id": tc.id,
                        "name": tc.function.name,
                        "content": json.dumps(result),
                    })
            continue

        return message.content

5. Execute and review

Running the agent on a small watchlist demonstrates the full loop in action.

if __name__ == "__main__":
    tickers = ["AAPL", "TSLA", "NVDA"]
    briefing = run_agent(tickers)
    print(briefing)

Run it

When I run the script, the agent typically produces output similar to this:


## Stock Briefing

**AAPL**
- Price: $223.45
- Change: +1.23%
- Outlook: Momentum remains steady ahead of earnings.

**TSLA**
- Price: $245.60
- Change: -0.85%
- Outlook: Slight pullback after last week's rally.

**NVDA**
- Price: $135.20
- Change: +2.10%
- Outlook: Strong buying interest continues in semiconductor space.

Because Oxlo.ai bills per request rather than per token, the cost of this multi-turn loop is predictable even when the context window grows with tool results. For teams running dozens of these agents on long schedules, that stability matters. See https://oxlo.ai/pricing for plan details.

Next steps

Swap yfinance for an internal database or REST API to turn this into a private research assistant. You can also add a second tool that fetches recent news headlines and instruct the model to correlate sentiment with price action, which pushes the agent into richer multi-tool planning territory.

Top comments (0)