> For the complete documentation index, see [llms.txt](https://docs.kumbaya.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kumbaya.xyz/developers/building-agents/overview.md).

# 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**](/developers/building-agents/agent-kit.md) wraps everything below into MCP tools an LLM can call directly - two servers ([on-chain MCP](/developers/building-agents/agent-kit/onchain-mcp.md) for the wallet, [api-mcp](/developers/building-agents/agent-kit/mcp.md) for the app), a [signer](/developers/building-agents/agent-kit/signer.md) 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](/developers/apis/exchange-api/quote.md) |
| **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](/developers/resources/indexer.md) 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](https://eips.ethereum.org/EIPS/eip-4361) signatures. This is the agent path; you don't need Privy.

```ts
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`](/developers/apis/exchange-api/quote.md) on `exchange.kumbaya.xyz`. One HTTPS call, returns calldata.
* **Search** → [`/api/v1/search`](/developers/apis/search-service.md) on `search.kumbaya.xyz`. No auth.
* **Indexed history (analytics, time-series, joins)** → [Hasura](/developers/resources/indexer.md) 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`](/developers/sdks/v3-sdk.md) for typed pool/position objects.

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

```graphql
subscription NewFireLaunches {
  FireToken(
    where: { chainId: { _eq: 4326 } }
    order_by: { createdAt: desc }
    limit: 10
  ) {
    address
    creator
    createdAt
    pool_id
    isToken0
  }
}
```

## 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](/developers/apis/exchange-api/quote.md), submit the returned calldata. \~1 round trip server-side.
* **Bundling Permit2 + swap or atomic batch:** use `UniversalRouter` via [`@kumbaya_xyz/universal-router-sdk`](/developers/sdks/universal-router-sdk.md).

End-to-end examples are in [**Quoting prices**](/developers/dex-integration/quoting.md) and [**Executing swaps**](/developers/dex-integration/swapping.md).

## Launching a token (programmatically)

```ts
import { fireLaunchAbi } from './abis/fireLaunch'
import { encodeFunctionData, parseUnits } from 'viem'

const FIRE_LAUNCH = '0x69FE0908F1211dE66F7067021998f28A5693ABbD' // mainnet
const WETH        = '0x4200000000000000000000000000000000000006'

// Mine a salt so the resulting token address is < numeraire (token must be token0).
// See "Token ordering and tick math" in the Launching a token guide.
const salt = mineToken0Salt({ deployer: FIRE_LAUNCH, numeraire: WETH, /* ... */ })

const txHash = await wallet.writeContract({
  address: FIRE_LAUNCH,
  abi: fireLaunchAbi,
  functionName: 'ignite',
  args: [{
    name:                 'My Agent Token',
    symbol:               'AGENT',
    totalSupply:          parseUnits('1000000000', 18),
    numeraire:            WETH,
    tickLower:            -219400,                 // canonical, indexed
    tickUpper:            -174800,                 // canonical, indexed
    feeTier:              10000,
    skimBps:              300,                    // 3%
    creatorAllocationBps: 0,
    maxShareToBeSoldBps:  7200,
    numPositions:         50,
    vestingDuration:      BigInt(90 * 24 * 60 * 60),
    salt,
  }],
})
```

> ⚠️ **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**](/developers/launchpad/launching.md#-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](/developers/apis/client-api.md#token-claim--eip-712-signature).

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:**

```ts
const fuelVault = '0x5aFaB54ac28a3bd485751146470D053b4FF11c81' // mainnet

// Read your liquid bucket
const liquid = await client.readContract({
  address: fuelVault,
  abi: fuelVaultAbi,
  functionName: 'creatorBuckets',
  args: [account.address, tokenAddress],
})

// Withdraw if non-zero
if (liquid.liquid > 0n) {
  await wallet.writeContract({
    address: fuelVault,
    abi: fuelVaultAbi,
    functionName: 'withdraw',
    args: [tokenAddress],
  })
}
```

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

```ts
const fireStream = '0x94d9582130745d0e2a1757dDEd8e730F5CDAd759' // mainnet

await wallet.writeContract({
  address: fireStream,
  abi: fireStreamAbi,
  functionName: 'claimFees',
  args: [tokenAddress],
})
```

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

```ts
// 1. Anyone can record the condition (starts grace timer).
//    recordGraduationCondition lives on FireLaunch, not FireGraduator.
await wallet.writeContract({
  address: fireLaunch,
  abi: fireLaunchAbi,
  functionName: 'recordGraduationCondition',
  args: [tokenAddress],
})

// 2. After gracePeriodDuration elapses, anyone can graduate (FireGraduator).
await wallet.writeContract({
  address: fireGraduator,
  abi: fireGraduatorAbi,
  functionName: 'graduate',
  args: [tokenAddress],
})
```

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**](/developers/building-agents/registry-config.md) for cast/viem snippets to read them on the fly.

## Where to next

* [**Kumbaya Agent Kit**](/developers/building-agents/agent-kit.md) - the whole stack as MCP tools + a skill pack, no glue code
* [**On-chain MCP**](/developers/building-agents/agent-kit/onchain-mcp.md) - the key-holding wallet server (swaps, liquidity, launches)
* [**Signer service**](/developers/building-agents/agent-kit/signer.md) - keyless signing for agent fleets
* [**Live registry config**](/developers/building-agents/registry-config.md) - read current registry values on-chain
* [**Auto-launch a token**](/developers/building-agents/launching-programmatically.md) - full programmatic launch recipe
* [**Sign in with Ethereum (SIWE)**](/developers/building-agents/siwe.md) - auth deep-dive
* [**Client API**](/developers/apis/client-api.md) - full API reference
* [**MCP Server**](/developers/building-agents/agent-kit/mcp.md) - the app APIs as MCP tools for LLM agents
* [**Hasura indexer**](/developers/resources/indexer.md) - subscription-friendly read path
