Skip to main content

Overview

Custom tools let the agent call functions you define. Instead of the agent completing everything in one shot, it can pause to request data or actions from your system, then continue once you provide the results. This enables use cases like:
  • Looking up order details from your database
  • Sending emails through your email service
  • Querying your internal APIs
  • Creating records in your CRM

How It Works

  1. You send a request with message + tools (your function definitions)
  2. The agent decides which tools to call based on the message
  3. If tools are needed, the API returns status: "requires_tool_outputs" with the tool calls
  4. You execute the functions in your system and submit the results
  5. The agent continues until it has a final answer (or needs more tool calls)
Credits are charged once on the initial request. Tool output submissions are free.

Defining Tools

Each tool needs a name, description, and parameters (JSON Schema format):
{
  "tools": [
    {
      "name": "get_order",
      "description": "Look up an order by ID and return its details",
      "parameters": {
        "type": "object",
        "properties": {
          "order_id": {
            "type": "string",
            "description": "The order ID to look up"
          }
        },
        "required": ["order_id"]
      }
    }
  ]
}

Tool Schema Rules

FieldTypeRequiredConstraints
namestringYesAlphanumeric + underscores, max 64 chars
descriptionstringYesMax 1,024 chars
parametersobjectYesMust have "type": "object"
Limits:
  • Maximum 20 tools per request
  • Maximum 10 tool call rounds per execution
  • 5-minute timeout between submissions
  • Maximum 100KB per tool output

Complete Example

Step 1: Send a request with tools

const response = await fetch('https://api.stewrd.dev/v1/agent', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${STEWRD_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    message: 'Check order #12345 and email the customer a summary',
    tools: [
      {
        name: 'get_order',
        description: 'Look up an order by ID',
        parameters: {
          type: 'object',
          properties: { order_id: { type: 'string' } },
          required: ['order_id'],
        },
      },
      {
        name: 'send_email',
        description: 'Send an email to a customer',
        parameters: {
          type: 'object',
          properties: {
            to: { type: 'string' },
            subject: { type: 'string' },
            body: { type: 'string' },
          },
          required: ['to', 'subject', 'body'],
        },
      },
    ],
  }),
})

const data = await response.json()

Step 2: Handle requires_tool_outputs

The response tells you which tools the agent wants to call:
{
  "id": "req-abc-123",
  "object": "agent.response",
  "status": "requires_tool_outputs",
  "tool_calls": [
    {
      "id": "call_xyz",
      "name": "get_order",
      "arguments": { "order_id": "12345" }
    }
  ],
  "usage": { "credits_remaining": 4997, "credits_this_request": 1 },
  "_compute_instance": "e784079b"
}

Step 3: Execute and submit results

Run the function in your system, then submit the output:
// Execute the tool call
const order = await db.orders.findById('12345')

// Submit the result
const continuation = await fetch(
  `https://api.stewrd.dev/v1/agent/${data.id}/tool-outputs`,
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${STEWRD_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      tool_outputs: [
        {
          tool_call_id: 'call_xyz',
          output: JSON.stringify(order),
        },
      ],
      _compute_instance: data._compute_instance,
    }),
  }
)

const result = await continuation.json()

Step 4: Get the final response

The agent may return another requires_tool_outputs (e.g., to send the email), or a completed response:
{
  "id": "req-abc-123",
  "object": "agent.response",
  "status": "completed",
  "message": "I've sent a summary email to jane@example.com with the shipping details for order #12345.",
  "usage": { "credits_this_request": 0, "tokens_used": 847 }
}

Handling the Loop

In production, wrap the tool call flow in a loop:
async function runWithTools(message: string, tools: Tool[]) {
  let response = await fetch('https://api.stewrd.dev/v1/agent', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${STEWRD_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ message, tools }),
  })

  let data = await response.json()

  while (data.status === 'requires_tool_outputs') {
    // Execute each tool call
    const outputs = await Promise.all(
      data.tool_calls.map(async (call: ToolCall) => ({
        tool_call_id: call.id,
        output: JSON.stringify(await executeToolCall(call)),
      }))
    )

    // Submit results
    response = await fetch(
      `https://api.stewrd.dev/v1/agent/${data.id}/tool-outputs`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${STEWRD_API_KEY}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          tool_outputs: outputs,
          _compute_instance: data._compute_instance,
        }),
      }
    )

    data = await response.json()
  }

  return data.message
}

Machine Affinity

The _compute_instance field ensures your tool output submissions are routed to the same server that holds the execution context. Always pass it back in subsequent requests.
If you omit _compute_instance, the request may be routed to a different machine and return a context_expired error.

Limitations

ConstraintLimit
Tools per request20
Tool call rounds10
Context TTL5 minutes
Output size per tool100KB
StreamingNot supported with tools
Platform capabilitiesChat only (no browser, code, etc.)

Error Codes

CodeHTTPDescription
invalid_tools400Tool definitions are malformed
invalid_tool_outputs400Tool outputs array is malformed
context_expired404Execution context expired (5-min TTL)
tool_output_too_large400Single output exceeds 100KB