Skip to content

Limits

This page documents all rate limits, size limits, and other constraints that apply to the Nodexa API.


Request Limits

Tools

Limit Value
Maximum tools per request 128
Maximum tool name length 64 characters
Allowed tool name characters Alphanumeric (a-z, A-Z, 0-9), underscore (_), hyphen (-)
Tool names must be unique Yes — within a single request

Tool names must match the pattern: ^[a-zA-Z0-9_-]{1,64}$

Examples:

  • get_weather — valid
  • lookup-order — valid
  • myTool123 — valid
  • my toolinvalid (space not allowed)
  • aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaainvalid (65 chars, exceeds limit)

Input

Limit Value
Maximum input messages in array Subject to the backing LLM's context window
Maximum instructions field length Subject to the backing LLM's context window

Context window limits

Nodexa does not enforce its own token limits on input. However, the request will fail if the total token count exceeds the context window of the LLM model backing the active specialist agent. Token limits vary by provider and model (e.g., 128k tokens for GPT-4o, 200k for Claude 3.5 Sonnet). Contact your Nodexa administrator for the models in use on your instance.


User Claims Limits

Limit Value
Maximum claimValue size 64KB (as JSONB)
Maximum claims per bulk request 50
Number of claims per user No enforced limit

Memory Limits

Limit Value
Number of memory items per user/assistant pair Managed by the platform — contact your administrator
Memory item content length Subject to platform configuration

API Key Limits

Limit Value
Keys per organization Configured by your administrator
Key expiry Keys do not expire automatically; must be explicitly revoked

Rate Limits

Rate limits are configured per-organization by your Nodexa administrator and depend on your deployment tier. When you exceed a rate limit, the API returns 429 Too Many Requests.

{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "You have exceeded the rate limit. Please wait before retrying."
  }
}

The response includes a Retry-After header indicating how many seconds to wait:

Retry-After: 5

Handling Rate Limits

async function callWithRateLimitRetry(fn, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (err) {
      if (err.status === 429) {
        const retryAfter = parseInt(err.headers?.['retry-after'] ?? '1', 10);
        console.warn(`Rate limited. Retrying in ${retryAfter}s...`);
        await new Promise(r => setTimeout(r, retryAfter * 1000));
        continue;
      }
      throw err;
    }
  }
  throw new Error('Max retries exceeded');
}

Streaming Connection Limits

Limit Value
Heartbeat interval 15 seconds (comment sent if no data for 15s)
Maximum stream duration Subject to your platform's proxy/load balancer configuration

Proxy and CDN timeouts

If your infrastructure uses a reverse proxy (Nginx, HAProxy) or CDN (Cloudflare, CloudFront), ensure idle connection timeouts are set higher than 15 seconds. The heartbeat is designed to keep connections alive for intermediaries with up to 15-second idle timeouts. If your proxy has a shorter timeout, configure it accordingly.


Bulk Operations

Operation Limit
POST /v1/user-claims/bulk Maximum 50 claims per request

For larger batches, split requests into chunks of 50:

async function bulkUpsertClaims(claims) {
  const CHUNK_SIZE = 50;

  for (let i = 0; i < claims.length; i += CHUNK_SIZE) {
    const chunk = claims.slice(i, i + CHUNK_SIZE);
    await fetch('/v1/user-claims/bulk', {
      method: 'POST',
      headers: {
        'x-api-key': process.env.NODEXA_API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ claims: chunk }),
    });
  }
}

Validation Reference

Tool Name Validation

// Check if a tool name is valid
function isValidToolName(name) {
  return /^[a-zA-Z0-9_-]{1,64}$/.test(name);
}

isValidToolName('get_weather'); // true
isValidToolName('lookup-order'); // true
isValidToolName('my tool'); // false (space)
isValidToolName('a'.repeat(65)); // false (too long)
isValidToolName(''); // false (empty)

Claim Value Size

// Estimate claim value size before submitting
function isClaimValueWithinLimit(value) {
  const json = JSON.stringify(value);
  const bytes = new TextEncoder().encode(json).length;
  return bytes <= 64 * 1024; // 64KB
}
import json

def is_claim_value_within_limit(value) -> bool:
    json_str = json.dumps(value)
    return len(json_str.encode('utf-8')) <= 64 * 1024  # 64KB