Skip to content

llmforagents/sdk

Repository files navigation

@llmforagents/sdk

npm version npm downloads License: MIT GitHub

Unified TypeScript SDK for the LLM4Agents platform — chat completions, wallet management, gasless stablecoin transfers, and MCP-powered tools through a single client.

Install

npm install @llmforagents/sdk

ethers is an optional peer dependency, required only for gasless transfers:

npm install ethers   # only needed for client.transfer

viem is an optional peer dependency, required only for x402 walk-up payments when using a viem.Account. The SDK also accepts any custom Signer implementation (see x402 Walk-up Payment below):

npm install viem     # only needed for x402 with viem accounts

Get an API Key

  1. Go to api.llm4agents.com/docs
  2. Register your agent to receive a key in the format sk-proxy-...
  3. Pass it to the client constructor:
const client = new LLM4AgentsClient({ apiKey: 'sk-proxy-...' })

Quick Start

import { LLM4AgentsClient } from '@llmforagents/sdk'

const client = new LLM4AgentsClient({ apiKey: 'sk-proxy-...' })

// Chat completion
const response = await client.chat.completions.create({
  model: 'anthropic/claude-sonnet-4',
  messages: [{ role: 'user', content: 'Hello' }],
})
console.log(response.choices[0]?.message.content)

// Conversation with MCP tools
const conv = client.chat.conversation({
  model: 'anthropic/claude-sonnet-4',
  system: 'You are a research assistant',
  tools: client.tools,
})
const answer = await conv.say('Search for Bitcoin news and summarize the top 3')
console.log(answer.content)

// Gasless stablecoin transfer (optional — requires ethers)
const result = await client.transfer.send({
  chain: 'polygon', token: 'USDC',
  to: '0xRecipient...', amount: '10.50',
  privateKey: '0x...',
})
console.log(result.txHash, result.explorerUrl)

Chat

Completions

// Non-streaming
const response = await client.chat.completions.create({
  model: 'anthropic/claude-sonnet-4',
  messages: [{ role: 'user', content: 'Hello' }],
})
console.log(response.choices[0]?.message.content)

// Streaming
const stream = await client.chat.completions.create({
  model: 'anthropic/claude-sonnet-4',
  messages: [{ role: 'user', content: 'Count to 10' }],
  stream: true,
})
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? '')
}

// With extended thinking
const response = await client.chat.completions.create({
  model: 'anthropic/claude-sonnet-4',
  messages: [{ role: 'user', content: 'Solve step by step: 47 * 83' }],
  reasoning: true,
  include_reasoning: true,
})

// Model fallback routing — tries primary first, falls back on error
const response = await client.chat.completions.create({
  models: ['anthropic/claude-sonnet-4', 'openai/gpt-4o'],
  messages: [{ role: 'user', content: 'Hello' }],
})

// Vision (multimodal) input
const analysis = await client.chat.completions.create({
  model: 'openai/gpt-4o',
  messages: [{
    role: 'user',
    content: [
      { type: 'text', text: 'What is in this image?' },
      { type: 'image_url', image_url: { url: 'https://example.com/image.png' } },
    ],
  }],
})

// Force/restrict tool use
const response = await client.chat.completions.create({
  model: 'openai/gpt-4o',
  messages: [...],
  tools: await client.tools.getDefinitions(),
  tool_choice: 'required',  // 'none' | 'auto' | 'required' | { type: 'function', function: { name: '...' } }
})

// With cancellation, header metadata, and final usage from streaming
const controller = new AbortController()
const stream = await client.chat.completions.create(
  { model: 'anthropic/claude-sonnet-4', messages: [...], stream: true },
  {
    signal: controller.signal,
    onMeta: (meta) => console.log('Request ID:', meta.requestId),
    // Fires when the SSE stream emits its final usage chunk (some providers send
    // include_usage=true). Use this for accurate token counts in streaming mode,
    // since cost-related response headers are sent before the body and don't
    // reflect the final token totals.
    onFinalUsage: (u) => console.log(`tokens: ${u.totalTokens} (reasoning: ${u.reasoningTokens ?? 0})`),
  },
)

Conversation with Tools

const conv = client.chat.conversation({
  model: 'anthropic/claude-sonnet-4',
  system: 'You are a research assistant',
  tools: client.tools,
  history: [],        // optional: rehydrate from persisted messages
  onToolCall: (name, args) => {
    console.log(`Calling ${name}...`)
    return true       // return false to cancel the tool call
  },
  onToolResult: (name, result) => {
    console.log(`${name} done (${result.text.length} chars)`)
  },
  onRoundMeta: (meta) => {
    console.log(`Round cost: $${(meta.costUsdCents ?? 0) / 100}, balance: $${(meta.balanceRemainingCents ?? 0) / 100}`)
  },
  onToolsIgnored: (model) => {
    console.warn(`${model} ignored the tools — model may not support function calling`)
  },
  enablePromptToolFallback: true,   // automatically retry in prompt mode when the model ignores tools
  maxToolRounds: 5,                 // default 10
})

// Single turn
const answer = await conv.say('Search for Bitcoin news and summarize the top 3')
console.log(answer.content)
console.log(answer.toolCalls)   // ToolCallRecord[] of executed tools
console.log(answer.usage)       // { promptTokens, completionTokens, totalTokens, reasoningTokens? }

// Streaming conversation
for await (const event of conv.stream('Now find the current price')) {
  switch (event.type) {
    case 'text':       process.stdout.write(event.content); break
    case 'reasoning':  process.stdout.write(`<think>${event.content}</think>`); break
    case 'meta':       console.log('Request ID:', event.meta.requestId); break
    case 'tool_start': console.log(`\n[tool] ${event.name}`); break
    case 'tool_end':   console.log(`[done] ${event.result.text.slice(0, 60)} (${event.durationMs}ms)`); break
    case 'fallback':   console.log(`\n[fallback] ${event.model} ignored tools — retrying in prompt mode`); break
    case 'done':       console.log('\n', event.response.usage); break
  }
}

// History management
const history = conv.messages   // readonly ChatMessage[] — JSON-serializable
conv.clear()                    // reset to empty, keeps system prompt
const branch = conv.fork()      // copy history into a new Conversation

onToolsIgnored(model) fires once when a model returns no tool calls on the first round despite being given tools — useful for detecting models without native function calling.

enablePromptToolFallback: true (default false) goes one step further: when the model ignores tools, the SDK automatically retries that round with the tool definitions injected into the system prompt and parses <tool_call>{"name":"...","arguments":{...}}</tool_call> blocks from the response text, then continues the loop as if the model had emitted native tool_calls. The stream() consumer additionally receives a { type: 'fallback' } event right before the prompt-mode tool execution begins. Costs one extra LLM round when fallback fires.

To restore a conversation from a previous session:

const conv = client.chat.conversation({
  model: 'anthropic/claude-sonnet-4',
  history: savedMessages,       // rehydrate from your store
})

McpToolResult

All tool calls return an McpToolResult instead of a plain string:

const result = await client.tools.scraper.fetchHtml({ url: 'https://example.com' })

result.text          // string — joined text from all text parts (convenience)
result.content       // readonly McpContent[] — typed content parts

for (const part of result.content) {
  if (part.type === 'text')     console.log(part.text)
  if (part.type === 'image')    console.log(part.mimeType, part.data.length)  // base64
  if (part.type === 'resource') console.log(part.uri, part.text)
}

The MCP transport auto-normalizes raw responses: snake_case mime_type is aliased to mimeType, imageBase64 / pngBase64 keys are mapped to data, MIME types are sniffed from base64 magic bytes when missing, and JSON-wrapped image/PDF payloads embedded inside text blocks (e.g. {"imageBase64": "...", "mimeType": "image/png"}) are auto-promoted to typed McpImageContent / McpResourceContent.

Agents

// Register a new agent — unauthenticated, call before you have an API key
const client = new LLM4AgentsClient({ apiKey: '' }) // empty key is fine for registration
const reg = await client.agents.register({ name: 'My Agent' })
// The returned apiKey is shown only once — save it immediately
console.log(reg.apiKey)           // sk-proxy-...
console.log(reg.depositDeadline)  // fund before this or the agent is deleted (15 min)
console.log(reg.notice)           // human-readable reminder

Wallets

// Generate a deposit wallet
const wallet = await client.wallets.generate({ chain: 'polygon', token: 'USDC' })
console.log(wallet.address)

// Check balance
const balance = await client.wallets.balance()
console.log(balance.availableUsd)
console.log(balance.wallets)    // WalletBalance[] — per-chain/token breakdown

// Transaction history
const txs = await client.wallets.transactions({ limit: 20, type: 'deposit' })
for (const tx of txs.transactions) {
  console.log(`${tx.type}: $${tx.amountUsdCents / 100}${tx.description}`)
}

TransactionFilter.type accepts 'deposit', 'usage', 'refund', or 'gas_sponsored'.

Gasless Transfers

Requires ethers ^6.0.0 installed as a peer dependency.

// One-call — resolves after the transaction is confirmed
const result = await client.transfer.send({
  chain: 'polygon', token: 'USDC',
  to: '0xRecipient...', amount: '10.50',
  privateKey: '0x...',
})
console.log(result.txHash, result.explorerUrl)

// Two-step — inspect the fee before committing
const quote = await client.transfer.quote({
  chain: 'polygon', token: 'USDC',
  from: '0xSender...', to: '0xRecipient...', amount: '10.50',
})
console.log(`Fee: ${quote.feeFormatted}`)
console.log(`Forwarder: ${quote.forwarderAddress}`)  // EIP-2771 forwarder used for the transfer

const result = await client.transfer.submit(quote, '0xPrivateKey...')
console.log(result.txHash)

x402 Walk-up Payment

The proxy supports the x402 protocol for per-request stablecoin payments on POST /v1/chat/completions. Instead of pre-funding an agent account, the client signs an EIP-3009 TransferWithAuthorization for USDC on Base / Base-Sepolia, attaches it as an X-PAYMENT header, and the proxy settles on-chain after the response is delivered.

Scope: this SDK signs x402 payments going OUT. The SDK builds and signs X-PAYMENT headers so your code can pay any x402-compatible server (the llm4agents API, an x402engine endpoint, or any third party). It does not include server-side helpers: there is no verifyPayment, no settlePayment, no requirePayment middleware. If your agent needs to receive x402 payments (run its own paywall), use a server library directly — @x402/hono for Hono, x402-express for Express, @coinbase/x402 for any framework, or the reference servers for other stacks. See Roadmap below for the server-side direction.

Two modes are mutually exclusive — pick one at construction time:

Mode Set via Required Use when
Bearer (default) omit payment or payment: { mode: 'bearer' } apiKey You have an agent and a pre-funded balance
x402 walk-up payment: { mode: 'x402', signer } signer (viem.Account or custom) You want one-shot calls billed per-request from a wallet, no agent registration

Bearer vs x402 — at a glance

// Bearer (existing) — pre-funded agent
const bearer = new LLM4AgentsClient({ apiKey: 'sk-proxy-...' })

// x402 walk-up — pay per call from a wallet
import { privateKeyToAccount } from 'viem/accounts'
import { viemAccountToSigner } from '@llmforagents/sdk'

const account = privateKeyToAccount('0xYOUR_PRIVATE_KEY')
const x402 = new LLM4AgentsClient({
  apiKey: '',                                    // not used in x402 mode
  payment: {
    mode: 'x402',
    signer: viemAccountToSigner(account),
    network: 'base-sepolia',                     // or 'base' for mainnet
  },
})

// Same API surface — the SDK probes the proxy for a 402, signs an
// EIP-3009 authorization, and retries with X-PAYMENT automatically.
const res = await x402.chat.completions.create({
  model: 'openai/gpt-4o-mini',
  messages: [{ role: 'user', content: 'Hello' }],
})

Custom signers (no viem dependency)

If you don't want to add viem, implement the Signer interface yourself — the SDK ships a Signer Port (Ports & Adapters) so any wallet stack works (ethers, hardware wallets, MPC, AWS KMS, …):

import type { Signer } from '@llmforagents/sdk'

const customSigner: Signer = {
  address: '0xYourAddress...',
  async signTypedData({ domain, types, primaryType, message }) {
    // Return a 0x-prefixed 65-byte signature.
    // Hardware wallet / KMS / ethers — your call.
    return '0x...'
  },
}

const client = new LLM4AgentsClient({
  apiKey: '',
  payment: { mode: 'x402', signer: customSigner, network: 'base' },
})

Streaming receipts

x402-mode streaming responses end with a trailing SSE event after [DONE] containing the on-chain settlement receipt. The Conversation.stream() helper surfaces this as a typed event:

const conv = x402.chat.conversation({ model: 'openai/gpt-4o-mini' })
for await (const ev of conv.stream('Tell me a joke')) {
  switch (ev.type) {
    case 'text':         process.stdout.write(ev.content); break
    case 'x402_receipt': console.log('\nsettled:', ev.transaction, ev.network); break
    case 'done':         console.log('\n', ev.response.usage); break
  }
}

For the lower-level chat.completions.create() API, pass onX402Receipt:

const stream = await x402.chat.completions.create(
  { model: 'openai/gpt-4o-mini', messages: [...], stream: true },
  {
    onX402Receipt: (receipt) => {
      console.log(`settled ${receipt.amount} on ${receipt.network}: ${receipt.transaction}`)
    },
  },
)

Lower-level helpers — client.x402

For advanced use cases (custom HTTP client, signing without sending, inspecting the 402 response shape), the client.x402 namespace exposes the building blocks:

// Probe the proxy and get the typed PaymentRequirements
const requirements = await x402.x402.probe()
console.log(requirements.maxAmountRequired, requirements.network)

// Probe + sign in one call — returns { paymentPayload, encodedHeader, requirements }
const signed = await x402.x402.sign()
// → signed.encodedHeader: base64-encoded X-PAYMENT value, ready to attach to a fetch()
// → signed.paymentPayload: the parsed PaymentPayload (typed, useful for logging/debugging)
// → signed.requirements: the proxy-advertised requirements the signature is bound to

// Sign against caller-supplied requirements (no HTTP) — useful for testing
// or batching signatures
const signed2 = await x402.x402.signFromRequirements(requirements)

Error handling

When the proxy rejects payment (signature invalid, nonce reused, etc.) the SDK throws X402PaymentRequiredError carrying the typed requirements so the caller can re-sign with a different amount or network:

import { X402PaymentRequiredError } from '@llmforagents/sdk'

try {
  await x402.chat.completions.create({ ... })
} catch (err) {
  if (err instanceof X402PaymentRequiredError) {
    console.error('Payment rejected. accepted offers:', err.paymentRequirements)
    console.error('x402 version:', err.x402Version)
  }
}

Networks: 'base' (mainnet, USDC 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913) and 'base-sepolia' (testnet, USDC 0x036CbD53842c5426634e7929541eC2318f3dCF7e) are currently supported. The USDC EIP-712 domain name differs between them (USD Coin vs USDC); viemAccountToSigner handles this automatically.

Endpoints accepting x402 (signed per-call USDC):

  • POST /v1/chat/completions — chat with any model (per-token signed upper bound)
  • POST /v1/scrape/{markdown,fetch_html,links,screenshot,pdf,extract} — one-shot scraping
  • POST /v1/search/{google,news,maps,batch} — Google search (Serper)
  • POST /v1/image/{generate,edit,analyze} — image generation / edit / vision

Per-call x402 prices are seeded ~10% below x402engine.app reference rates (e.g. scrape markdown ~$0.0045, screenshot ~$0.009, image gen ~$0.0135-$0.045). Prices are admin-editable from the operator panel without redeploy.

Browser sessions (session_*) and other endpoints (/v1/embeddings, /api/v1/wallets/*, etc.) stay Bearer-only — sessions are pre-deposit by design.

REST scrape / search / image with x402

The same payment: { mode: 'x402', signer, network } client config that works for chat completions also works for the MCP REST surface. Use the bundled MCP client methods if you prefer the JSON-RPC API; use fetch / a direct HTTP client for the REST surface:

import { LLM4AgentsClient } from '@llmforagents/sdk'
import { privateKeyToAccount } from 'viem/accounts'
import { viemAccountToSigner } from '@llmforagents/sdk'

const x402 = new LLM4AgentsClient({
  apiKey: '',
  payment: {
    mode: 'x402',
    signer: viemAccountToSigner(privateKeyToAccount('0xYOUR_KEY')),
    network: 'base-sepolia',
  },
})

// Probe + sign + retry handled automatically by the transport
const markdown = await x402.x402.sign().then((signed) =>
  fetch('https://api.llm4agents.com/v1/scrape/markdown', {
    method: 'POST',
    headers: { 'content-type': 'application/json', 'x-payment': signed.encodedHeader },
    body: JSON.stringify({ url: 'https://example.com' }),
  }).then((r) => r.json()),
)

The MCP tools accessor (client.tools.scraper.markdown(...) etc.) currently uses Bearer auth via the MCP transport; the REST surface above is the path for walk-up.

Roadmap — server-side x402

Today the SDK is client-only: it signs X-PAYMENT headers so an agent can pay for outbound services. The mirror direction (an agent serving its own paywalled endpoint and receiving x402 payments from third parties) is not implemented and not on the v2.x roadmap.

If you want to monetize your agent with x402, use a server library directly:

Stack Library
Hono (Cloudflare Workers, Bun, Deno, Node) @x402/hono
Express x402-express
Any framework (low-level, JWT-auth'd CDP facilitator) @coinbase/x402
Other stacks see the x402 reference servers

If a first-class @llmforagents/sdk-server (verify/settle/middleware helpers around @coinbase/x402 with llm4agents-flavoured defaults) would help your use case, open an issue at llmforagents/sdk.

MCP Tools

Scraper

const html  = await client.tools.scraper.fetchHtml({ url: 'https://example.com' })
const md    = await client.tools.scraper.markdown({ url: 'https://example.com' })
const links = await client.tools.scraper.links({ url: 'https://example.com' })
const shot  = await client.tools.scraper.screenshot({ url: 'https://example.com', fullPage: true })
const pdf   = await client.tools.scraper.pdf({ url: 'https://example.com' })
const data  = await client.tools.scraper.extract({
  url: 'https://example.com',
  schema: { type: 'object', properties: { title: { type: 'string' } } },
})

All scraper methods accept an optional proxy field: 'none', 'datacenter', or 'residential'.

Browser sessions

const session = await client.tools.scraper.sessionCreate({})
const result  = await client.tools.scraper.sessionExec({
  sessionId: session.text,
  actions: [{ type: 'navigate', url: 'https://example.com' }],
})
const status  = await client.tools.scraper.sessionStatus({ sessionId: session.text })
await client.tools.scraper.sessionClose({ sessionId: session.text })

Search

const results = await client.tools.search.google({ q: 'TypeScript SDK design' })
const news    = await client.tools.search.googleNews({ q: 'Bitcoin', tbs: 'qdr:d' })
const places  = await client.tools.search.googleMaps({ q: 'coffee near me' })
const batch   = await client.tools.search.batchSearch({ queries: ['python', 'golang'] })

Image

const img      = await client.tools.image.generate({ prompt: 'A robot writing code' })
const edited   = await client.tools.image.edit({ prompt: 'Make it blue', imageUrl: '...' })
const analysis = await client.tools.image.analyze({ prompt: 'What is this?', imageUrl: '...' })

Tool Definitions

client.tools.definitions returns ToolDefinition[] | undefined (populated after the first tool call). Use client.tools.getDefinitions() to eagerly fetch and cache the list:

const defs = await client.tools.getDefinitions()   // ToolDefinition[] in OpenAI function format

Pass these definitions to any LLM that supports function calling, or let the conversation() helper manage them automatically when tools: client.tools is set.

Models

const result = await client.models.list()
for (const m of result.models) {
  console.log(`${m.slug} — $${m.inputPricePer1M}/1M in, $${m.outputPricePer1M}/1M out`)
  if (m.feePct !== undefined) console.log(`  platform fee: ${m.feePct}%`)
}

// Filter by name
const filtered = await client.models.list({ search: 'claude' })

models.list() returns a ModelListResult with .models (array), .requestId (string | undefined), and .feePct (number | undefined — the platform fee percentage applied as a default for models that don't override it).

Embeddings

const res = await client.embeddings.create({
  model: 'openai/text-embedding-3-large',
  input: 'How many vectors fit in a haystack?',
})
console.log(res.data[0].embedding.length)  // → e.g. 3072
console.log(res.usage.prompt_tokens, res.model)

// Batch input
const batch = await client.embeddings.create({
  model: 'openai/text-embedding-3-small',
  input: ['first', 'second', 'third'],
})
batch.data.forEach((item) => console.log(item.index, item.embedding))

embeddings.create() accepts an OpenAI-compatible request — model (slug), input (string or string array, max 2048 entries), and the optional encoding_format, dimensions, and user fields. The response shape mirrors OpenAI's: { object, data: [{ embedding, index, object }], model, usage: { prompt_tokens, total_tokens } }. Embeddings have no completion tokens, so billing is input-only — the actual model that responded is reported in the X-Model-Used response header (also surfaced via the onMeta callback).

Catalog: Embedding models do not appear in OpenRouter's public catalog endpoint, so the proxy maintains them by hand. New embedding models can be added through the admin panel — see model_type='embedding' rows.

Error Handling

All errors are instances of LLM4AgentsError:

import { LLM4AgentsClient, LLM4AgentsError } from '@llmforagents/sdk'

try {
  await client.chat.completions.create({ ... })
} catch (err) {
  if (err instanceof LLM4AgentsError) {
    console.error(err.code, err.statusCode, err.requestId, err.message)
  }
}
code HTTP status Description
auth_error 401, 403 Invalid or missing API key
insufficient_balance 402 Not enough balance to cover the request
rate_limited 429 Too many requests
model_not_found 404 Requested model does not exist in the catalog
model_disabled 422 Model exists but is currently disabled
context_overflow Prompt + max_tokens exceeds the model's context window
gas_spike 409 Network gas price spiked above safe threshold during transfer
signature_mismatch 422 EIP-712 permit signature could not be verified
invalid_token 422 Unsupported token or chain for gasless transfer
operator_unavailable 503 Gasless relayer is temporarily unavailable
deadline_expired 400 EIP-712 permit deadline passed before submission
tool_not_found MCP tool name not found in the server's tool list
tool_execution_error MCP tool returned an error result
tool_loop_limit Conversation exceeded maxToolRounds without a final answer
network_error fetch threw (DNS failure, TCP reset, etc.)
timeout Request exceeded the configured timeout
api_error 4xx, 5xx Any other non-success response

Constructor Options

const client = new LLM4AgentsClient({
  apiKey:  'sk-proxy-...',                          // required for Bearer; empty in x402 mode
  baseUrl: 'https://api.llm4agents.com',            // optional
  mcpUrl:  'https://mcp.llm4agents.com/mcp',        // optional
  timeout: 30_000,                                  // optional, ms, default 30s
  payment: { mode: 'bearer' },                      // optional, default; or { mode: 'x402', signer, network? }
})

What's New in v2.5

  • x402 walk-up payment mode — pay per-request from a wallet on /v1/chat/completions without registering an agent. Pass payment: { mode: 'x402', signer, network } to the client constructor. Supports both viem.Account (via viemAccountToSigner) and any custom Signer implementation (ethers, KMS, hardware wallets) thanks to the Ports & Adapters design.
  • Streaming responses emit a typed x402_receipt event after [DONE], surfacing the on-chain settlement receipt (transaction, network, amount, payer) to conv.stream() consumers and the onX402Receipt callback on chat.completions.create().
  • New client.x402 namespace — probe(path, body), sign(requirements), and signFromRequirements(req) helpers for low-level integrations.
  • New exports: X402PaymentRequiredError, viemAccountToSigner, buildTransferWithAuthorizationTypedData, generateNonce, signFromRequirements, encodePaymentHeader, decodePaymentRequiredHeader, pickSupportedRequirements, USDC_ADDRESS_BY_NETWORK, USDC_DOMAIN_NAME_BY_NETWORK, X402_CAIP2_BY_NETWORK, TRANSFER_WITH_AUTHORIZATION_TYPES, and types Signer, PaymentConfig, PaymentRequirements, PaymentPayload, X402Network, X402Receipt.
  • x402 allowlist extended to the MCP REST surface — clients in x402 mode can now hit /v1/scrape/*, /v1/search/*, and /v1/image/* in addition to chat. Prices are admin-editable in cents from the operator panel (parallel value for balance / x402_value for walk-up per tool).

What's New in v2.4

  • client.embeddings.create() — OpenAI-compatible embeddings against POST /v1/embeddings. Pass a string or array of up to 2048 strings; receive { data: EmbeddingItem[], model, usage } with input-only billing. Embedding-model catalog is curated by hand on the server because OpenRouter omits embedding models from its public catalog endpoint.
  • New types exported: EmbeddingsCreateParams, EmbeddingsResponse, EmbeddingItem, EmbeddingsUsage, EmbeddingsOptions.

Migration from v1.x

Before (v1) After (v2)
await tools.call(name, args)string result.text (or full McpToolResult)
onToolResult: (name, result: string) result is now McpToolResult — use result.text
await client.models.list()ModelInfo[] result.models (access via .models)
conv.stream() tool_end event .result: string .result is now McpToolResult

v2.0.1 → v2.1.0

Before (v2.0.1) After (v2.1.0)
model.inputPricePer1m model.inputPricePer1M (capital M)
model.outputPricePer1m model.outputPricePer1M (capital M)
Tool errors silenced as text Tool errors throw LLM4AgentsError
gas_sponsored missing from transaction filter type: 'gas_sponsored' now valid

Migration from @llm4agents/gasless

@llm4agents/gasless is deprecated. Replace it with @llmforagents/sdk:

Before (@llm4agents/gasless) After (@llmforagents/sdk)
new GaslessClient({ apiKey }) new LLM4AgentsClient({ apiKey })
gc.transfer(params) client.transfer.send(params)
gc.quote(params) client.transfer.quote(params)
gc.send(quote, key) client.transfer.submit(quote, key)
GaslessError LLM4AgentsError
err.code values Identical — same string literal codes
QuoteResult, TransferResult shapes Identical

License

MIT

About

SDK in Typescript for use in AI services provided by llm4agents.com

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors