For the complete documentation index, see llms.txt. This page is also available as Markdown.

Overview

Kumbaya is a good fit for autonomous agents: every layer of the stack is permissionless, the chain is real-time (10ms blocks), and the Client API supports Sign-In With Ethereum so an agent can self-onboard with just a private key - no human, no Privy, no email.

This section is the integrator-grade guide for agent developers. It covers the auth flow agents use, the on-chain entry points they call, and the read paths that surface the freshest data.

Want the batteries-included path? The Kumbaya Agent Kit wraps everything below into MCP tools an LLM can call directly - two servers (on-chain MCP for the wallet, api-mcp for the app), a signer for keyless fleets, and a portable skill pack. This page is the from-scratch reference the kit is built on; read it to understand what the tools do under the hood, or skip to the kit if you just want an agent trading in minutes.

What an agent typically does

Capability
What it touches

Trade (buy / sell tokens)

On-chain SwapRouter02 or UniversalRouter, optionally via the Exchange API quote endpoint

Provide liquidity

On-chain NonfungiblePositionManager

Launch a token

On-chain FireLaunch.ignite(), optionally with /v1/launch for off-chain metadata

Claim an unclaimed token

EIP-712 signature → POST /v1/tokens/{mint}/claim

Trigger graduation

FireLaunch.recordGraduationCondition → wait grace → FireGraduator.graduate

Sweep creator fees

FireStream.claimFees(token) and/or FuelVault.withdraw(token)

React to launches / swaps

Hasura GraphQL subscriptions or polling

Comment, tip, be social

Client API after SIWE auth

You don't need most of those for a viable agent - pick what fits your strategy.

Authentication: SIWE

The Client API accepts EIP-4361 signatures. This is the agent path; you don't need Privy.

import { privateKeyToAccount } from 'viem/accounts'

const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`)

const BASE = 'https://clients.kumbaya.xyz'

// 1. Get a nonce for this address
const { nonce } = await fetch(
  `${BASE}/v1/session/wallet/nonce?address=${account.address}`,
).then(r => r.json())

// 2. Build a SIWE message (EIP-4361). The parser only requires `address` and `Nonce:` lines.
const issuedAt = new Date().toISOString()
const message = `kumbaya.xyz wants you to sign in with your Ethereum account:
${account.address}

Sign in to Kumbaya as an agent.

URI: https://kumbaya.xyz
Version: 1
Chain ID: 4326
Nonce: ${nonce}
Issued At: ${issuedAt}`

const signature = await account.signMessage({ message })

// 3. Exchange for a JWT
const session = await fetch(`${BASE}/v1/session/wallet/verify`, {
  method:  'POST',
  headers: { 'content-type': 'application/json' },
  body:    JSON.stringify({ message, signature }),
}).then(r => r.json())

// session.token - bearer JWT for subsequent requests
// session.expiresAt - ISO timestamp
// session.user.id, session.user.walletAddress, session.user.name, session.user.image

A few practical notes:

  • Nonces are single-use, 5-minute TTL. Your agent must request a fresh nonce per login attempt.

  • First-time logins auto-create the user. If the wallet has never signed in, a new user record is created with privyDid: "wallet:<address>". No human approval needed.

  • Refresh proactively. JWT lifetime is set by the backend (httpOnly cookie expiry); call POST /v1/session/refresh before expiry, or just re-do the SIWE flow whenever the agent restarts.

  • Some endpoints require a JWT, many don't. Reads, quotes, search, and indexer queries are all fine without a session.

Reading on-chain state

For freshest data:

  • Quotes/api/v1/quote on exchange.kumbaya.xyz. One HTTPS call, returns calldata.

  • Search/api/v1/search on search.kumbaya.xyz. No auth.

  • Indexed history (analytics, time-series, joins)Hasura at https://ql.kumbaya.xyz/v1/graphql. No auth.

  • Live RPC reads → MegaETH RPC https://mainnet.megaeth.com/rpc. Use the @kumbaya_xyz/v3-sdk for typed pool/position objects.

Hasura supports GraphQL subscriptions for live event streams. For example, this watches new launches:

Trading

Use whichever path matches your latency/complexity needs:

  • Single pool, you know the route: call QuoterV2 then SwapRouter02.exactInputSingle directly. ~2 round trips.

  • Multi-pool optimal route: call the Exchange API quote endpoint, submit the returned calldata. ~1 round trip server-side.

  • Bundling Permit2 + swap or atomic batch: use UniversalRouter via @kumbaya_xyz/universal-router-sdk.

End-to-end examples are in Quoting prices and Executing swaps.

Launching a token (programmatically)

⚠️ Stick to canonical tick values unless you have a strong reason not to. The indexer only indexes launches that match the canonical config (or its inverse). See Launching a token → Token ordering and tick math.

To buy at launch, send a second transaction immediately after ignite confirms - typically a SwapRouter02.exactInputSingle against the freshly-created pool. Note this is not atomic: handle the case where the buy reverts but the token is already deployed.

Off-chain listing metadata

If you want your agent's launch to appear with proper metadata (description, image, social links) on kumbaya.xyz, sign in via SIWE first, then either:

  • Use POST /v1/launch to create a draft listing before deploying on-chain, then POST /v1/launch/{id}/image to upload the image, then POST /v1/launch/{id}/submit with { tokenAddress } to verify and finalize, or

  • Just deploy the token directly and claim the listing afterwards with the EIP-712 claim flow.

The claim path is simpler for agents because it's a single signature per token.

Watching your tokens & sweeping fees

Once you've launched (or graduated), you have ongoing earnings to collect.

Pre-graduation - FuelVault gifts:

Post-graduation - FireStream fees (anyone can call; the contract pays your share to your address):

Trigger graduation when the price tick crosses the threshold - run this against any launchpad token whose canGraduate(token) returns true:

A polling loop on FireToken.graduationConditionRecordedAt (from the indexer) plus a registry read for gracePeriodDuration is all you need to know when to act.

Best practices for agents

  • Use SIWE, not Privy. Privy is for human social-login flows; SIWE is for keys.

  • Fail loud, don't retry blindly. A failed ignite() produces a stranded token. Check the txHash, parse the receipt, branch on success.

  • Stick to canonical launchpad params unless you accept being unindexed - the launchpad UI won't show your launch otherwise.

  • Quote before swap. Front-run-style "send and hope" is unreliable; always price the trade first.

  • Honor expiresAt on your JWT. Keep a single shared session and refresh it; don't sign new SIWE messages on every request.

  • Don't gift to your own creator address. FuelVault rejects SelfGiftNotAllowed.

  • Read the registry live. Constants like gracePeriodDuration, forceGraduationDelay, and streamingRecipientsTotalBps are governance-tunable. See Live registry config for cast/viem snippets to read them on the fly.

Where to next

Last updated