Skip to main content

Agents API

Manage agents within your tenant. Each agent gets encrypted EVM and Solana wallets on creation.

Create Agent

Creates an agent with encrypted wallet keypairs.
POST /agents
Auth: Tenant API key Request Body:
{
  id: string;        // Unique agent ID (1-128 alphanumeric, _ - . :)
  name: string;      // Display name
  platformId?: string; // Optional external platform ID
}
Response:
{
  "ok": true,
  "data": {
    "id": "my-agent",
    "name": "My Trading Agent",
    "tenantId": "your-tenant",
    "walletAddresses": {
      "evm": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
      "solana": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"
    },
    "createdAt": "2026-03-26T12:00:00.000Z"
  }
}
const agent = await steward.createWallet("my-agent", "My Trading Agent");

List Agents

Returns all agents for the authenticated tenant.
GET /agents
Auth: Tenant API key Response:
{
  "ok": true,
  "data": [
    {
      "id": "my-agent",
      "name": "My Trading Agent",
      "tenantId": "your-tenant",
      "walletAddresses": { "evm": "0x742d...", "solana": "7xKXtg..." },
      "createdAt": "2026-03-26T12:00:00.000Z"
    }
  ]
}
const agents = await steward.listAgents();

Get Agent

Returns a single agent by ID.
GET /agents/:agentId
Auth: Tenant API key or agent JWT
const agent = await steward.getAgent("my-agent");

Delete Agent

Permanently deletes an agent and all associated data (wallets, policies, transactions).
DELETE /agents/:agentId
Auth: Tenant API key (agent tokens cannot delete) Response:
{
  "ok": true,
  "data": { "deleted": "my-agent" }
}
This cascades: encrypted keys, wallet entries, policies, transactions, and approval queue items are all deleted. This cannot be undone.
curl -X DELETE https://api.steward.fi/agents/my-agent \
  -H "X-Steward-Key: your-key"

Generate Agent Token

Creates a scoped JWT for agent-level operations.
POST /agents/:agentId/token
Auth: Tenant API key (agents cannot generate their own tokens) Request Body:
{
  expiresIn?: string; // JWT expiry (e.g., "24h", "7d"). Default: "24h"
}
Response:
{
  "ok": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "agentId": "my-agent",
    "tenantId": "your-tenant",
    "scope": "agent",
    "expiresIn": "24h"
  }
}
curl -X POST https://api.steward.fi/agents/my-agent/token \
  -H "X-Steward-Key: your-key" \
  -H "Content-Type: application/json" \
  -d '{"expiresIn": "24h"}'

Get Account

Returns the agent’s aggregated digital-asset account, including wallet rows, native balance, token portfolio assets, USD totals when pricing is configured, spend summary, signing capabilities, and gas sponsorship state.
GET /agents/:agentId/account?chainId=8453&tokens=0xUSDC,0xDAI
Auth: Agent JWT or tenant key Response:
{
  "ok": true,
  "data": {
    "id": "my-agent",
    "type": "agent",
    "agentId": "my-agent",
    "walletAddress": "0x742d35Cc...",
    "wallets": [{ "chainFamily": "evm", "address": "0x742d35Cc..." }],
    "portfolio": {
      "chainId": 8453,
      "native": { "symbol": "ETH", "formatted": "1.0", "usdValueText": "3000" },
      "tokens": [],
      "totalUsdText": "3000"
    },
    "capabilities": ["sign_transaction", "sign_message", "transfer"],
    "sponsorship": { "enabled": false }
  }
}
const account = await steward.getAgentAccount("my-agent", {
  chainId: 8453,
  tokens: ["0xUSDC..."],
});

Get Balance

Returns the native token balance for an agent’s wallet.
GET /agents/:agentId/balance?chainId=8453
Auth: Agent JWT or tenant key Response:
{
  "ok": true,
  "data": {
    "agentId": "my-agent",
    "walletAddress": "0x742d35Cc...",
    "balances": {
      "native": "1000000000000000000",
      "nativeFormatted": "1.0",
      "chainId": 8453,
      "symbol": "ETH"
    }
  }
}
const balance = await steward.getBalance("my-agent", 8453);

Get Token Balances

Returns ERC-20 token balances for an agent’s wallet.
GET /agents/:agentId/tokens?chainId=8453&tokens=0xUSDC,0xDAI
Auth: Agent JWT or tenant key Response:
{
  "ok": true,
  "data": {
    "agentId": "my-agent",
    "walletAddress": "0x742d35Cc...",
    "chainId": 8453,
    "native": {
      "symbol": "ETH",
      "balance": "1000000000000000000",
      "formatted": "1.0"
    },
    "tokens": [
      { "address": "0xUSDC...", "symbol": "USDC", "balance": "1000000", "formatted": "1.0" }
    ]
  }
}

Authorization Keys and Key Quorums

Agent signers model owners, delegated signers, service signers, and quorum members for an agent wallet. A signer with keyType: "p256" and a registered publicKey is Steward’s Privy-style asymmetric authorization key. A signer with keyType: "hmac" can instead receive a one-time delegated credential secret when created with issueCredential: true.
GET /agents/:agentId/signers?status=active
POST /agents/:agentId/signers
PATCH /agents/:agentId/signers/:signerId
DELETE /agents/:agentId/signers/:signerId
Auth: Owner/admin browser session. Create, revoke, and authority-changing updates require recent MFA. Signer request body:
{
  signerType: "owner" | "delegated" | "service" | "quorum_member";
  subjectType: "user" | "wallet" | "api_key" | "external";
  subjectId: string;
  keyType?: "hmac" | "p256"; // default: "hmac"
  publicKey?: string | null; // required for keyType: "p256"
  address?: string | null;
  chainFamily?: "evm" | "solana" | null;
  label?: string | null;
  permissions?: string[];
  policyIds?: string[]; // policy rule ids on this same agent
  metadata?: Record<string, unknown>;
  issueCredential?: boolean; // hmac only; returns credentialSecret once
}
const key = await steward.createAuthorizationKey("my-agent", {
  signerType: "delegated",
  subjectType: "external",
  subjectId: "ops-key-1",
  keyType: "p256",
  publicKey: "BASE64_SPKI_P256_PUBLIC_KEY",
  permissions: ["sign_message", "sign_transaction"],
  policyIds: ["policy_daily_limit"],
});
policyIds must reference policy rules on the same agent. Updating a signer’s policy scope is an authority-changing operation and requires recent MFA:
await steward.updateAuthorizationKey("my-agent", key.id, {
  status: "paused",
  policyIds: ["policy_daily_limit", "policy_manual_review"],
});
Signer responses include id, signerType, subjectType, subjectId, keyType, publicKey, permissions, policyIds, status, metadata, hasCredential, and timestamps. credentialSecret is returned only on the create response when issueCredential: true; it is never returned by list or update calls. Key quorums group signer IDs and optional child quorum IDs behind a threshold. Nested quorum verification is bounded and fails closed on cycles or excessive depth.
GET /agents/:agentId/key-quorums?status=active
POST /agents/:agentId/key-quorums
PATCH /agents/:agentId/key-quorums/:quorumId
DELETE /agents/:agentId/key-quorums/:quorumId
const quorum = await steward.createAgentKeyQuorum("my-agent", {
  name: "Treasury approval",
  threshold: 2,
  memberSignerIds: ["signer-a"],
  memberQuorumIds: ["child-quorum-a"],
  permissions: ["sign_transaction"],
});

Batch Create

Create multiple agents in one request with optional shared policies.
POST /agents/batch
Auth: Tenant API key Request Body:
{
  agents: Array<{ id: string; name: string; platformId?: string }>;
  applyPolicies?: PolicyRule[];  // Applied to all created agents
}
Response:
{
  "ok": true,
  "data": {
    "created": [/* AgentIdentity[] */],
    "errors": [/* { id: string, error: string }[] */]
  }
}
const result = await steward.createWalletBatch(
  [
    { id: "agent-1", name: "Agent One" },
    { id: "agent-2", name: "Agent Two" },
  ],
  [{ id: "limit", type: "spending-limit", enabled: true, config: { maxPerDay: "1000000000000000000" } }]
);