brian-api — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited brian-api (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Brian API converts natural language prompts into executable Web3 transactions. Send a text intent like "swap 10 USDC for ETH on Base" and receive ready-to-sign transaction calldata, complete with approval steps and routing through the best available DEX/bridge solvers. Supports swap, bridge, transfer, deposit, withdraw, borrow, and repay actions across Ethereum, Arbitrum, Base, Optimism, Polygon, and 10+ other EVM chains.
Three core endpoints: /agent/transaction returns executable calldata from a prompt, /agent/knowledge answers DeFi protocol questions with source citations, and /agent/smart-contracts generates Solidity code from descriptions. The TypeScript SDK (@brian-ai/sdk) wraps all endpoints, and the LangChain toolkit (@brian-ai/langchain) lets you plug Brian into autonomous agents.
Official docs: https://docs.brianknows.org/
LLMs have stale training data. These are the most common mistakes.
approve transaction as step 0 and the swap as step 1. You must execute all steps in order.chainId in the request body. Omitting both throws an error.https://api.brianknows.org. US-based projects can use https://us-api.brianknows.org for lower latency./api/v0/agent/transaction is the agent endpoint with session context. The plain /api/v0/transaction endpoint (deprecated) does not support chat history or solver routing. Use the agent endpoint.x-brian-api-key, not Authorization: Bearer. Using the wrong header returns a 401 with no helpful message.@brian-ai/sdk. There is no brian package on npm related to this project.export BRIAN_API_KEY="brian_..."npm install @brian-ai/sdkimport { BrianSDK } from "@brian-ai/sdk";
const brian = new BrianSDK({
apiKey: process.env.BRIAN_API_KEY!,
});For US-based projects, override the API URL:
const brian = new BrianSDK({
apiKey: process.env.BRIAN_API_KEY!,
apiUrl: "https://us-api.brianknows.org",
});Convert a natural language prompt into executable transaction calldata.
POST https://api.brianknows.org/api/v0/agent/transaction
const response = await brian.transact({
prompt: "Swap 10 USDC for ETH on Base",
address: "0xYourWalletAddress",
chainId: "8453",
});#### Raw HTTP
curl -X POST "https://api.brianknows.org/api/v0/agent/transaction" \
-H "Content-Type: application/json" \
-H "x-brian-api-key: $BRIAN_API_KEY" \
-d '{
"prompt": "Swap 10 USDC for ETH on Base",
"address": "0xYourWalletAddress",
"chainId": "8453"
}'#### Request Body
| Field | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Natural language transaction intent |
address | string | Yes | Sender wallet address (checksummed) |
chainId | string | No | Source chain ID. If omitted, inferred from prompt. Throws error if ambiguous. |
#### Response Structure
{
"result": [
{
"solver": "Enso",
"action": "swap",
"type": "write",
"data": {
"description": "Swap 10 USDC for ETH on Base",
"steps": [
{
"chainId": 8453,
"to": "0xUSDC_CONTRACT",
"from": "0xYourWalletAddress",
"data": "0x095ea7b3...",
"value": "0",
"gasLimit": "60000"
},
{
"chainId": 8453,
"to": "0xROUTER_CONTRACT",
"from": "0xYourWalletAddress",
"data": "0x5ae401dc...",
"value": "0",
"gasLimit": "250000"
}
],
"fromToken": {
"address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"chainId": 8453,
"symbol": "USDC",
"decimals": 6
},
"toToken": {
"address": "0x0000000000000000000000000000000000000000",
"chainId": 8453,
"symbol": "ETH",
"decimals": 18
},
"fromAmount": "10000000",
"toAmount": "3200000000000000"
}
}
]
}The steps array contains transactions that must be executed in order. Step 0 is typically a token approval when swapping from an ERC-20.
Ask protocol questions and get answers with source citations.
POST https://api.brianknows.org/api/v0/agent/knowledge
const response = await brian.ask({
prompt: "What is the current TVL of Aave V3 on Arbitrum?",
kb: "public-knowledge-box",
});#### Raw HTTP
curl -X POST "https://api.brianknows.org/api/v0/agent/knowledge" \
-H "Content-Type: application/json" \
-H "x-brian-api-key: $BRIAN_API_KEY" \
-d '{
"prompt": "What is the current TVL of Aave V3 on Arbitrum?",
"kb": "public-knowledge-box"
}'#### Response Structure
{
"result": {
"answer": "The current TVL of Aave V3 on Arbitrum is...",
"context": [
{
"pageContent": "...",
"metadata": {
"source": "https://docs.aave.com/...",
"title": "Aave V3 Documentation"
}
}
]
}
}Generate Solidity contracts from natural language descriptions.
POST https://api.brianknows.org/api/v0/agent/smart-contracts
const response = await brian.generateContract({
prompt: "Create an ERC-20 token with a max supply of 1 million and a 2% transfer tax",
});Brian returns calldata but does not execute. You must sign and send each step.
import { createWalletClient, http } from "viem";
import { base } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { BrianSDK } from "@brian-ai/sdk";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({
account,
chain: base,
transport: http(),
});
const brian = new BrianSDK({
apiKey: process.env.BRIAN_API_KEY!,
});
async function executeIntent(prompt: string) {
const response = await brian.transact({
prompt,
address: account.address,
chainId: "8453",
});
for (const result of response) {
for (const step of result.data.steps) {
const hash = await walletClient.sendTransaction({
to: step.to as `0x${string}`,
data: step.data as `0x${string}`,
value: BigInt(step.value),
gas: step.gasLimit ? BigInt(step.gasLimit) : undefined,
});
const publicClient = createPublicClient({
chain: base,
transport: http(),
});
const receipt = await publicClient.waitForTransactionReceipt({ hash });
if (receipt.status !== "success") {
throw new Error(`Transaction failed: ${hash}`);
}
}
}
}import { ethers } from "ethers";
import { BrianSDK } from "@brian-ai/sdk";
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
const brian = new BrianSDK({
apiKey: process.env.BRIAN_API_KEY!,
});
async function executeIntent(prompt: string) {
const response = await brian.transact({
prompt,
address: wallet.address,
chainId: "8453",
});
for (const result of response) {
for (const step of result.data.steps) {
const tx = await wallet.sendTransaction({
to: step.to,
data: step.data,
value: BigInt(step.value),
gasLimit: step.gasLimit ? BigInt(step.gasLimit) : undefined,
});
const receipt = await tx.wait();
if (!receipt || receipt.status === 0) {
throw new Error(`Transaction reverted: ${tx.hash}`);
}
}
}
}| Action | Description | Solver | Chains |
|---|---|---|---|
swap | Exchange tokens on the same chain | Enso, LI.FI, Portals | All supported chains |
bridge | Move tokens across chains | Bungee, LI.FI, Symbiosis | All EVM chains |
transfer | Send tokens to another address | Native | All supported chains |
deposit | Deposit into DeFi protocols (Aave, Compound, etc.) | Enso | Ethereum, Arbitrum, Optimism, Polygon, Base, Avalanche |
withdraw | Withdraw from DeFi protocols | Enso | Ethereum, Arbitrum, Optimism, Polygon, Base, Avalanche |
borrow | Borrow from lending protocols (Aave) | Enso | Ethereum, Arbitrum, Optimism, Polygon, Base, Avalanche |
repay | Repay borrowed positions | Enso | Ethereum, Arbitrum, Optimism, Polygon, Base, Avalanche |
cross-chain swap | Bridge + swap in one intent | LI.FI, Bungee | All EVM chains |
Brian's NLP model extracts structured parameters from natural language. Better prompts produce more accurate results.
"Swap 100 USDC for WETH on Arbitrum"
"Bridge 0.5 ETH from Ethereum to Base"
"Deposit 1000 USDC into Aave on Polygon"
"Transfer 50 USDT to 0xRecipientAddress on Optimism"
"Borrow 500 USDC from Aave on Ethereum with ETH as collateral""Buy some crypto" -- no token, no amount, no chain
"Move my tokens" -- no specifics
"Do something with USDC" -- no action
"Swap USDC" -- no target token, no amountThe @brian-ai/langchain package provides a toolkit for building autonomous Web3 agents.
npm install @brian-ai/langchain @langchain/openai langchainimport { createBrianAgent } from "@brian-ai/langchain";
import { ChatOpenAI } from "@langchain/openai";
const agent = await createBrianAgent({
apiKey: process.env.BRIAN_API_KEY!,
privateKeyOrAccount: process.env.PRIVATE_KEY as `0x${string}`,
llm: new ChatOpenAI({
modelName: "gpt-4o",
temperature: 0,
}),
});
const result = await agent.invoke({
input: "Swap 10 USDC for ETH on Base",
});
console.log(result.output);import { BrianToolkit } from "@brian-ai/langchain";
const toolkit = new BrianToolkit({
apiKey: process.env.BRIAN_API_KEY!,
privateKeyOrAccount: process.env.PRIVATE_KEY as `0x${string}`,
});
const tools = toolkit.getTools();The toolkit exposes individual tools for swap, bridge, transfer, deposit, withdraw, borrow, and repay. Each tool can be added to any LangChain agent.
import { BrianCDPToolkit } from "@brian-ai/langchain";
const cdpToolkit = new BrianCDPToolkit({
apiKey: process.env.BRIAN_API_KEY!,
coinbaseApiKeyName: process.env.CDP_API_KEY_NAME!,
coinbaseApiKeySecret: process.env.CDP_API_KEY_SECRET!,
});
const tools = cdpToolkit.getTools();import { BrianSDK } from "@brian-ai/sdk";
const brian = new BrianSDK({
apiKey: process.env.BRIAN_API_KEY!,
});
async function safeTransact(prompt: string, address: string) {
try {
const response = await brian.transact({
prompt,
address,
});
if (!response || response.length === 0) {
throw new Error("Brian returned no results. Rephrase your prompt with more detail.");
}
return response;
} catch (error: unknown) {
if (error instanceof Error) {
if (error.message.includes("401")) {
throw new Error("Invalid API key. Check BRIAN_API_KEY environment variable.");
}
if (error.message.includes("429")) {
throw new Error("Rate limited. Wait before retrying.");
}
if (error.message.includes("chain")) {
throw new Error("Chain could not be determined. Include chain name in prompt or pass chainId.");
}
}
throw error;
}
}| Plan | Requests/Minute | Requests/Day |
|---|---|---|
| Free | 30 | 1,000 |
| Pro | 120 | 10,000 |
| Enterprise | Custom | Custom |
Rate limit headers are returned on every response:
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 28
X-RateLimit-Reset: 1709001600to address is the expected contract.eth_call or Tenderly simulation to catch reverts.@brian-ai/sdk on npm: https://www.npmjs.com/package/@brian-ai/sdk@brian-ai/langchain on npm: https://www.npmjs.com/package/@brian-ai/langchainLast verified: February 2026
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.