I got tired of jumping between Yahoo Finance, a broker dashboard, and a Google News tab every time I wanted a quick read on a stock. What I actually wanted: type a question, get a grounded answer that pulls live prices, recent earnings, and current news in one shot.
Turns out you can wire this up in an afternoon with Vercel AI SDK and Valyu's financeSearch + webSearch tools. Here's how.
What we're building
A Node.js CLI agent you run like this:
npx tsx agent.ts "What's happening with NVDA? Give me price, recent earnings, and any news I should know about."
It streams back a real answer, not a hallucinated one, pulled from live financial data and current web sources.
Setup
You need two things:
- A Valyu API key - free $10 credit when you sign up at platform.valyu.ai
- An Anthropic API key (or swap in OpenAI/any other AI SDK provider)
pnpm add ai @ai-sdk/anthropic @valyu/ai-sdk
Create a .env file:
VALYU_API_KEY=your-valyu-key
ANTHROPIC_API_KEY=your-anthropic-key
The agent
// agent.ts
import { streamText, stepCountIs } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { financeSearch, webSearch } from "@valyu/ai-sdk";
const query = process.argv[2] ?? "What's the current price and outlook for AAPL?";
const result = streamText({
model: anthropic("claude-3-5-sonnet-20241022"),
messages: [
{
role: "system",
content: `You are a stock market analyst with access to live financial data and web search.
- Use financeSearch for stock prices, earnings, dividends, balance sheets, and insider transactions
- Use webSearch for recent news, analyst sentiment, and market context
- Always cite sources
- Be specific: include actual numbers, dates, and figures from your search results`,
},
{
role: "user",
content: query,
},
],
tools: {
financeSearch: financeSearch(),
webSearch: webSearch(),
},
stopWhen: stepCountIs(5),
});
for await (const chunk of result.textStream) {
process.stdout.write(chunk);
}
console.log("\n");
That's the whole thing. The agent loop is handled by stepCountIs(5), the model keeps calling tools until it has enough data to answer, up to 5 steps.
How it works
When you run it, the agent:
- Receives your question
- Decides which tools to call (
financeSearch,webSearch, or both) - Gets results back. Real prices, actual earnings figures, live news
- Synthesizes an answer with citations
- Streams it back token by token
The financeSearch tool pulls from stock prices, earnings reports, income statements, balance sheets, dividend history, and insider transaction data. webSearch covers current news, analyst coverage, and anything else on the open web.
For a query like "What's happening with NVDA?" you'd typically see it call financeSearch for price and recent earnings, then webSearch for news about data center demand or any recent analyst upgrades, then combine them into a coherent analysis.
Extending it
A few directions from here:
Add more tools for deeper research:
import { secSearch, economicsSearch } from "@valyu/ai-sdk";
tools: {
financeSearch: financeSearch(),
webSearch: webSearch(),
sec: secSearch(), // 10-K, 10-Q, 8-K filings
economics: economicsSearch(), // FRED, BLS macro data
},
Compare multiple tickers:
content: "Compare MSFT and GOOGL on trailing P/E, revenue growth, and recent earnings beats"
The agent will run parallel searches and give you a side-by-side.
Control costs with config options:
financeSearch({
maxNumResults: 5, // fewer results = lower cost
relevanceThreshold: 0.8, // only high-quality matches
})
What the data actually covers
financeSearch isn't just price tickers. It pulls from:
- Historical and real-time stock, crypto, and forex prices
- Earnings per share, revenue, and guidance
- Balance sheets, income statements, cash flow
- Insider buy/sell transactions (Form 4 data)
- Dividend history
So queries like "How have TSLA insiders been trading over the last 6 months?" or "What's Apple's free cash flow trend since 2021?" work out of the box.
Running it
npx tsx agent.ts "Is AMD a buy right now? Give me current price, latest earnings, and analyst sentiment."
Sample output (abridged):
AMD is currently trading at $X.XX, down X% today...
Recent Earnings (Q4 2024):
- Revenue: $X.XB (beat estimates by X%)
- EPS: $X.XX vs $X.XX expected
- Data center segment grew XX% YoY...
Analyst Sentiment:
According to recent coverage from [source], consensus is...
The numbers are real. The sources are cited. No hallucination.
The Underlying API
Under the hood, @valyu/ai-sdk is a thin wrapper around Valyu's DeepSearch API. If you want to build a custom tool, one that only searches specific financial sources, you can drop down to the raw tool() from the AI SDK:
import { tool } from "ai";
import { z } from "zod";
const cryptoSearch = tool({
description: "Search cryptocurrency price and market data",
inputSchema: z.object({
query: z.string(),
}),
execute: async ({ query }) => {
const response = await fetch("https://api.valyu.ai/v1/search", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.VALYU_API_KEY,
},
body: JSON.stringify({
query,
search_type: "proprietary",
included_sources: ["valyu/valyu-crypto"],
max_num_results: 5,
}),
});
return response.json();
},
});
Full list of available sources and parameters at docs.valyu.ai.
Code
Full example is a single file, agent.ts , above is all you need. If you build something on top of this, the main things to think about are:
- System prompt quality matters a lot for financial queries. Be explicit about what each tool is for
- stepCountIs(5) is usually enough for single-stock analysis; bump to 8-10 for comparative research
- Stream the output for better UX - streamText over generateText
The Valyu finance data covers benchmarks like 73% accuracy on 120 finance questions vs 55% for Google search, which matters when you're asking specific questions about earnings or insider activity where precision is the point.
Top comments (2)
The "jumping between Yahoo Finance, a broker dashboard, and a Google News tab" problem resonated hard. I run a 24/7 AI agent that among other things helps manage a browser-based personal finance tool, and the context-switching tax is real — not just for humans, but for agents too.
What caught my attention is
stepCountIs(5)as the loop bound. In my experience running an always-on agent, the step count sweet spot varies wildly by query complexity. Single-ticker "what's the price" needs 1-2 steps, but "compare MSFT and GOOGL on trailing P/E" probably saturates all 5. Have you found queries that silently degrade because 5 steps wasn't enough? The failure mode is subtle — the agent just omits data it didn't have time to fetch, and the answer looks complete.Two genuine questions:
Data freshness window: financeSearch pulls "real-time" prices, but what's the actual latency? 15-minute delayed data (standard for free feeds) vs true real-time changes the answer to "is AMD a buy right now" meaningfully. For an agent making tool calls in a chain, even a 30-second cache could compound — step 1 gets price X, step 3 gets news from 2 minutes later referencing price Y.
Hallucination detection in financial context: You mention 73% accuracy on 120 finance questions. The scary part is the other 27%. In most domains, a hallucinated answer is annoying. In finance, a hallucinated earnings number could inform actual trading decisions. Do you do any post-hoc verification — like cross-referencing the financeSearch result against a second source before presenting it as fact?
The
included_sourcespattern in the raw API is clever. Being able to scope searches to specific data providers feels like the financial equivalent of pinning a dependency version — you know exactly what you're getting.Hey, great questions!
As for the step count, with Vercel AI SDK, a single step can be multiple tool calls, so often 5 is more than enough for reasoning/tools/reasoning/tools/response - however this is flexible and can be increased!
The data freshness from Valyu is live! there is no 15-minute delay, can go down to minute levels, and SEC filings for example are searchable as soon as they are released in realtime
Yes the agent will do cross referencing to reduce hallucinations as it is very critical domain