@vaaya/sdk
v0.1.0
Published
Vaaya SDK for agent builders: give deployed agents the whole pay-per-call catalog (x402, MPP and REST services), routed capabilities (onesearch, onescrape, onefind), an OpenAI-compatible LLM endpoint and a spend ceiling on every call, with one API key.
Readme
Vaaya for TypeScript
Use one Vaaya account to call paid APIs, run research, generate media, and give customer agents their own spending limits. The client uses Node.js 20 or later and has no required runtime dependencies.
Install
npm install @vaaya/sdkSet VAAYA_API_KEY to a key from API keys.
Keep the key in your server environment, never in browser code.
import { Vaaya } from '@vaaya/sdk'
const vaaya = new Vaaya() // Reads VAAYA_API_KEY.
const result = await vaaya.one.search({ query: 'recent advances in battery recycling' })
console.log(result.data)
console.log(result.chargedCents) // Actual charge, including fractional cents.This search has a default ceiling of 5¢. Paid calls use your Vaaya balance and are subject to the API key's limits. A refused or failed service call is not charged.
Call any service
const result = await vaaya.use('exa/search', { query: 'battery recycling', numResults: 5 }, {
maxCostCents: 5,
idempotencyKey: 'research-request-123',
})Known service/action IDs infer their parameters from the canonical catalog.
The SDK ships generated ServiceParams types and checks them for drift. Dynamic
IDs and { service, action } objects remain supported for newly added services.
Provider-specific outputs remain unknown; pass a response type to use<T>()
when your application knows the provider's contract.
A spending ceiling caps the price of one call. Reusing an idempotency key lets you retry the same request without starting a second purchase. The SDK does not automatically retry paid requests.
const service = await vaaya.catalog.get('exa/search') // Schema, price, rail.
const matches = await vaaya.catalog.discover('company data') // Free.
const plan = await vaaya.consult('Find battery recycling companies in Germany') // 1¢.
// Read plan.message and plan.calls before executing the suggested calls.Other shortcuts: one.scrape, one.crawl, one.find, one.enrich, and
one.searchDeep. They return the same receipt shape as use.
Wait for a job
const started = await vaaya.one.crawl({ url: 'https://example.com', max_pages: 20 })
if (started.jobId) {
const job = await vaaya.result(started.jobId, { wait: true, timeoutMs: 120_000 })
console.log(job.status, job.result)
}Polling is free. You can also pass wait: true to use or a one method.
Requests and polling accept an AbortSignal. Cancelling a wait stops local
polling; it does not cancel a job that has already started on the server.
Give each agent its own key
const agent = await vaaya.agents.create({
externalId: 'customer-42', label: 'Support agent', ceilingCents: 500, period: 'month',
})
// Store agent.key now: create and rotate return the secret once.
await vaaya.agents.update(agent.id, { paused: true })
await vaaya.agents.update(agent.id, { ceilingCents: 2000, paused: false })
const rotated = await vaaya.agents.rotate(agent.id)
await vaaya.agents.revoke(agent.id)Writes require your account's primary key. Sub-agent keys cannot create keys,
raise their own limits, or manage other agents. agents() and agents.list()
both return the account's agents. wallet() and transactions() return account
balances and receipts. You can manage agents in the dashboard.
Use your agent framework
Install the framework separately. Importing the main SDK does not load any framework. The optional adapters use the framework versions listed below; follow that framework's Node.js requirement (AI SDK 7 needs Node.js 22+).
// OpenAI Agents SDK 0.18+
import { Agent } from '@openai/agents'
import { openaiAgentTools } from '@vaaya/sdk/openai-agents'
const agent = new Agent({ name: 'Research assistant', tools: openaiAgentTools(vaaya) })
// Vercel AI SDK 5–7
import { generateText } from 'ai'
import { vaayaTools } from '@vaaya/sdk/ai'
// Supply a model from your installed provider adapter.
const response = await generateText({ model, prompt: 'Research battery recycling', tools: vaayaTools(vaaya) })For a custom tool loop, openaiTools(vaaya) returns Chat Completions definitions
and a handle(name, args) function. responsesTools(vaaya) returns the distinct,
flat Responses API shape. anthropicTools(vaaya) returns Anthropic tool definitions.
All three use the same handlers and preserve spend-gate errors for your application.
LLMs and paid URLs
await vaaya.llm.chat({ messages: [{ role: 'user', content: 'Hello' }] })
// Or configure an OpenAI client with vaaya.llm.baseURL and vaaya.llm.apiKey.
const fetched = await vaaya.fetch('https://merchant.example/resource', {}, { maxCostCents: 10 })
console.log(fetched.body, fetched.chargedCents)llm.chat is non-streaming and defaults to the auto model. Use an OpenAI client
for streaming. fetch pays x402/MPP challenges from your balance; it requires
the server's PAID_FETCH_ENABLED flag and an explicit ceiling.
Handle errors
import { VaayaError } from '@vaaya/sdk'
try {
await vaaya.one.search({ query: 'battery recycling' })
} catch (error) {
if (error instanceof VaayaError) {
console.error(error.code, error.status, error.message)
if (error.isSpendGate) console.error(error.cardUrl ?? error.creditsUrl)
}
}Errors retain the API's code, status, response body, and retry hint. Local errors
include aborted, timeout, network_error, and invalid_response. Transport
errors do not prove that a submitted paid request failed; retry with its original
idempotency key or check its receipt.
Constructor options: apiKey, baseUrl, agentTag, timeoutMs (default 300000),
and an injectable fetch. Both ESM and CommonJS exports include type declarations.
Maintainers: see release instructions.
