Skip to content
ESC

Searching...

Quick Links

Type to search • Press to navigate • Enter to select

Keep typing to search...

No results found

No documentation matches ""

Tool Discovery.

Discover available API operations as machine-readable tool definitions.

Jun 9, 2026

The /tools endpoint lets your agent discover what it can do. It returns machine-readable tool definitions scoped to the authenticated key's role and permissions. No manual tool configuration needed.

How It Works

sequenceDiagram
    participant Agent as Your Agent
    participant API as Agent API

    Note over Agent: 1. Agent starts up
    Agent->>API: GET /api/agent/v1/tools?format=openai
    Note over API: Reads agent-api.json<br/>Filters by key's role<br/>Filters by key's scopes<br/>Filters by permissions<br/>Formats for framework
    API-->>Agent: Tool definitions (JSON)
    Note over Agent: 2. Passes tools to LLM provider

    Agent->>API: POST, GET, PUT... (tool calls)
    Note over Agent: 3. LLM calls tools →<br/>Agent routes to Agent API
    API-->>Agent: API responses

Your agent calls /tools once at startup, then uses the returned definitions for all subsequent LLM interactions.

Request

curl -X GET https://your-domain.com/api/agent/v1/tools?format=openai \
  -H "X-Agent-Key: rl_agent_..."
Parameter Type Default Description
format string generic Output format: openai, anthropic, mcp, or generic

Response

{
  "error": false,
  "tools": [ ... ],
  "meta": {
    "role": "partner",
    "format": "openai",
    "tool_count": 46,
    "cached": false
  }
}

The meta section includes how many tools are available and whether this response was served from cache.

Supported Formats

OpenAI Function Calling (?format=openai)

Returns tools in the OpenAI function calling format. Each tool is a type: "function" object with name, description, and parameters schema.

[
  {
    "type": "function",
    "function": {
      "name": "list_loyalty_cards",
      "description": "List all loyalty cards for this partner\n...\n\nHTTP: GET /api/agent/v1/partner/cards",
      "parameters": {
        "type": "object",
        "properties": {
          "page": { "type": "integer", "default": 1 },
          "per_page": { "type": "integer", "default": 25 }
        },
        "required": []
      }
    }
  }
]

Anthropic/Claude Tool Use (?format=anthropic)

Returns tools in the Anthropic tool use format. Each tool has name, description, and input_schema.

[
  {
    "name": "record_purchase",
    "description": "Record a purchase and award loyalty points\n...\n\nHTTP: POST /api/agent/v1/partner/transactions/purchase",
    "input_schema": {
      "type": "object",
      "properties": { ... },
      "required": ["card_id", "member_identifier", "purchase_amount"]
    }
  }
]

MCP (?format=mcp)

Returns tools in the Model Context Protocol format. Wrapped in a { "tools": [...] } envelope with inputSchema for each tool.

Generic JSON Schema (?format=generic)

Returns a self-documenting format with method, path, scopes, and full parameter schemas as first-class fields. Suitable for custom integrations, Zapier/Make/n8n, and any platform that can consume JSON.

{
  "api_name": "Reward Loyalty Agent API",
  "api_version": "1.1.0",
  "base_url": "/api/agent/v1",
  "auth": {
    "type": "api_key",
    "header": "X-Agent-Key"
  },
  "tools": [
    {
      "name": "list_loyalty_cards",
      "description": "List all loyalty cards for this partner",
      "method": "GET",
      "path": "/api/agent/v1/partner/cards",
      "required_scopes": ["read", "write:cards"],
      "parameters": { ... }
    }
  ]
}

Schema Preservation

Tool parameters preserve the full JSON Schema structure from the OpenAPI spec. This includes:

  • Translatable fields. oneOf: [string, object] for fields that accept either a plain string or a locale-keyed object ({"en": "...", "nl": "..."})
  • Nested objects. Object-typed properties with their own sub-properties
  • Arrays. Array-typed properties with items schema
  • Enums, patterns, min/max, format. All JSON Schema keywords pass through

This means your LLM receives accurate type information for every parameter, including complex types.

Role, Scope & Permission Filtering

The /tools endpoint returns tools the authenticated key can use, nothing more. Three filtering layers apply:

Role Filtering

  • Partner keys see partner endpoints and the health check
  • Admin keys see admin endpoints and the health check
  • Member keys see member endpoints and the health check

Scope Filtering

  • Keys with limited scopes (e.g., read) see the endpoints their scopes grant access to, nothing more
  • Keys with the admin super-scope see all endpoints for their role

Permission Filtering (Partner)

Partner keys are subject to two layers of permission checks:

Top-level API access. If agent_api_permission is false for the partner, /tools returns 403 FEATURE_DISABLED. The response matches what the partner would receive from any partner endpoint.

{
  "error": true,
  "code": "FEATURE_DISABLED",
  "message": "Agent API access has been revoked for this partner.",
  "retry_strategy": "contact_support",
  "details": { "permission": "agent_api_permission" }
}

Sub-feature filtering. If the partner has API access but individual features are disabled, the platform excludes the gated endpoints from the tool list. Calling them would return 403 FEATURE_DISABLED:

Feature Permission Endpoints Hidden When Disabled
loyalty_cards_permission All loyalty card and reward CRUD
stamp_cards_permission All stamp card CRUD and stamp/redeem operations
vouchers_permission All voucher CRUD and validate/redeem operations

This means two partner keys with the same scopes but different plans may see different tool sets.

The /tools endpoint does not appear in its own tool list. A tool that lists tools adds noise for agents.

CLI Export

You can also export tool definitions via the command line:

# Default: generic format, partner role
php artisan agent:export-tools

# OpenAI format for admin endpoints
php artisan agent:export-tools openai --role=admin

# Claude format for member endpoints
php artisan agent:export-tools anthropic --role=member

# Read partner tools (no writes)
php artisan agent:export-tools generic --role=partner --scopes=read

Output is saved to storage/api-docs/agent-tools-{format}.json.

Caching

The platform caches tool definitions for 24 hours per unique combination of spec version, key role, scopes, feature permissions, and format. The cache invalidates when:

  • The OpenAPI spec is regenerated (spec version/filemtime changes)
  • A different combination of role + scopes + permissions is requested

No manual cache:clear is needed.

Error Responses

Status Code Meaning
403 FEATURE_DISABLED Partner's Agent API access has been revoked (agent_api_permission = false).
422 INVALID_FORMAT Unsupported format parameter. Use: openai, anthropic, mcp, or generic.
503 TOOLS_UNAVAILABLE The OpenAPI spec has not been generated yet. Run php artisan l5-swagger:generate agent.

Integration Example

A complete integration with OpenAI:

import openai, requests, json

AGENT_KEY = "rl_agent_..."
BASE_URL = "https://your-domain.com"

# 1. Discover tools (once at startup)
resp = requests.get(
    f"{BASE_URL}/api/agent/v1/tools?format=openai",
    headers={"X-Agent-Key": AGENT_KEY}
)
tools = resp.json()["tools"]

# 2. Pass to OpenAI
response = openai.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Award 50 points to [email protected]"}],
    tools=tools,
)

# 3. Execute the tool call
tool_call = response.choices[0].message.tool_calls[0]
fn = tool_call.function
desc = next(t["function"]["description"] for t in tools if t["function"]["name"] == fn.name)
http_line = [l for l in desc.split("\n") if l.startswith("HTTP:")][0]
method, path = http_line.replace("HTTP: ", "").split(" ", 1)

result = requests.request(
    method=method,
    url=f"{BASE_URL}{path}",
    headers={"X-Agent-Key": AGENT_KEY},
    json=json.loads(fn.arguments),
)
print(result.json())