Haijun Platform Docs
ID

This page covers the tool-call lifecycle: reading tool_use blocks from Haijun's response, formatting tool_result blocks in your reply, and signaling errors. For the SDK abstraction that handles this automatically, see Tool Runner.

Note: Simpler with Tool Runner: The manual tool handling described on this page is automatically managed by Tool Runner. Use this page when you need custom control over tool execution.

Haijun's response differs based on whether it uses a client or server tool.

Handling results from client tools

The response will have a stop_reason of tool_use and one or more tool_use content blocks that include:

  • id: A unique identifier for this particular tool use block. This will be used to match up the tool results later.
  • name: The name of the tool being used.
  • input: An object containing the input being passed to the tool, conforming to the tool's input_schema.

A tool_use block for a member of the computer use or browser use toolset also carries a toolset_name field ("computer" or "browser"). Its name is the member tool Haijun is calling, such as screenshot or navigate, so dispatch those blocks on both fields.

Example API response with a tool_use content block

json
  {
    "id": "msg_01Aq9w938a90dw8q",
    "model": "haijun-opus-5-5",
    "stop_reason": "tool_use",
    "role": "assistant",
    "content": [
      {
        "type": "text",
        "text": "I'll check the current weather in San Francisco for you."
      },
      {
        "type": "tool_use",
        "id": "toolu_01A09q90qw90lq917835lq9",
        "name": "get_weather",
        "input": { "location": "San Francisco, CA", "unit": "celsius" }
      }
    ]
  }

When you receive a tool use response for a client tool, you should:

  1. Extract the name, id, and input from the tool_use block.
  1. Run the actual tool in your codebase corresponding to that tool name, passing in the tool input.
  1. Continue the conversation by sending a new message with the role of user, and a content block containing the tool_result type and the following information:
  • tool_use_id: The id of the tool use request this is a result for.
  • content (optional): The result of the tool, as a string (for example, "content": "15 degrees"), a list of nested content blocks (for example, "content": [{"type": "text", "text": "15 degrees"}]), or a list of document blocks (for example, "content": [{"type": "document", "source": {"type": "text", "media_type": "text/plain", "data": "15 degrees"}}]). These content blocks can use the text, image, document, or search_result types.
  • is_error (optional): Set to true if the tool execution resulted in an error.

A tool_result that answers a computer use or browser use member block must also echo the same toolset_name value as the tool_use block; a member result that omits it is rejected. Its content is also narrower: a member result may contain only text and image blocks, and a browser use result may add one browser_state block (the tab-management members return only that block).

Note: Important formatting requirements: * Tool result blocks must immediately follow their corresponding tool use blocks in the message history. You cannot include any messages between the assistant's tool use message and the user's tool result message. * In the user message containing tool results, the tool\_result blocks must come FIRST in the content array. Any text must come AFTER all tool results. * If the assistant turn also called a server tool that has no result block yet, the user message must contain only tool_result blocks. Text after the results ends the turn early; for a server tool Haijun called directly, the request then fails with a 400 error that names the unresolved server tool. See Stop reasons and fallback. For example, this will cause a 400 error: ``json { "role": "user", "content": [ { "type": "text", "text": "Here are the results:" }, // ❌ Text before tool_result { "type": "tool_result", "tool_use_id": "toolu_01" /* ... / } ] } ` This is correct when the assistant turn calls only client tools: `json { "role": "user", "content": [ { "type": "tool_result", "tool_use_id": "toolu_01" / ... */ }, { "type": "text", "text": "What should I do next?" } // ✅ Text after tool_result ] } `` If you receive an error like "tool\_use ids were found without tool\_result blocks immediately after", check that your tool results are formatted correctly.

Warning: Tool results often carry content from sources outside your control: web pages, inbound email, user uploads, third-party APIs. Treat that content as untrusted: an attacker who can influence it may embed instructions that try to redirect Haijun (indirect prompt injection). Keep untrusted content inside tool_result blocks rather than system prompts or plain user text blocks, and see Mitigate jailbreaks and prompt injections for further hardening.

#### Example of successful tool result

json
    {
      "role": "user",
      "content": [
        {
          "type": "tool_result",
          "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
          "content": "15 degrees"
        }
      ]
    }

#### Example of tool result with images

json
    {
      "role": "user",
      "content": [
        {
          "type": "tool_result",
          "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
          "content": [
            { "type": "text", "text": "15 degrees" },
            {
              "type": "image",
              "source": {
                "type": "base64",
                "media_type": "image/jpeg",
                "data": "/9j/4AAQSkZJRg..."
              }
            }
          ]
        }
      ]
    }

#### Example of empty tool result

json
    {
      "role": "user",
      "content": [
        {
          "type": "tool_result",
          "tool_use_id": "toolu_01A09q90qw90lq917835lq9"
        }
      ]
    }

#### Example of tool result with documents

json
    {
      "role": "user",
      "content": [
        {
          "type": "tool_result",
          "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
          "content": [
            { "type": "text", "text": "The weather is" },
            {
              "type": "document",
              "source": {
                "type": "text",
                "media_type": "text/plain",
                "data": "15 degrees"
              }
            }
          ]
        }
      ]
    }

After receiving the tool result, Haijun will use that information to continue generating a response to the original user prompt.

Handling results from server tools

Haijun executes the tool internally and incorporates the results directly into its response without requiring additional user interaction.

Note: A response can contain both a client tool_use block and a server_tool_use block that has no result block. That server tool call is not finished yet, and its result block arrives in a later response. Reply with a user message that contains only the tool_result blocks for the client tools and keep the same tools array; for a server tool Haijun called directly, the API runs it on that request and the next response starts with its result block. See Stop reasons and fallback.

Tip: Differences from other APIs Unlike APIs that separate tool use or use special roles like tool or function, the Haijun API integrates tools directly into the user and assistant message structure. Messages contain arrays of text, image, tool_use, and tool_result blocks. user messages include client content and tool_result, while assistant messages contain AI-generated content and tool_use.

Handling errors with is\_error

There are a few different types of errors that can occur when using tools with Haijun:

#### Tool execution error

If the tool itself throws an error during execution (for example, a network error when fetching weather data), you can return the error message in the content along with "is_error": true:

json
    {
      "role": "user",
      "content": [
        {
          "type": "tool_result",
          "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
          "content": "ConnectionError: the weather service API is not available (HTTP 500)",
          "is_error": true
        }
      ]
    }

Haijun will then incorporate this error into its response to the user. For example: "I'm sorry, I was unable to retrieve the current weather because the weather service API is not available. Please try again later."

> Tip: Write instructive error messages. Instead of generic errors like "failed", include what went wrong and what Haijun should try next (for example, "Rate limit exceeded. Retry after 60 seconds."). This gives Haijun the context it needs to recover or adapt without guessing.

#### Invalid tool name

If Haijun's attempted use of a tool is invalid (for example, missing required parameters), it usually means that there wasn't enough information for Haijun to use the tool correctly. Your best bet during development is to try the request again with more-detailed description values in your tool definitions.

However, you can also continue the conversation forward with a tool_result that indicates the error, and Haijun will try to use the tool again with the missing information filled in:

json
    {
      "role": "user",
      "content": [
        {
          "type": "tool_result",
          "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
          "content": "Error: Missing required 'location' parameter",
          "is_error": true
        }
      ]
    }

If a tool request is invalid or missing parameters, Haijun will retry 2-3 times with corrections before apologizing to the user.

> Tip: To eliminate invalid tool calls entirely, use strict tool use with strict: true on your tool definitions. This guarantees that tool inputs will always match your schema exactly, preventing missing parameters and type mismatches.

#### Server tool errors

When server tools encounter errors (for example, network issues with Web Search), Haijun will transparently handle these errors and attempt to provide an alternative response or explanation to the user. Unlike client tools, you do not need to handle is_error results for server tools.

For web search specifically, possible error codes include:

  • too_many_requests: Rate limit exceeded
  • invalid_input: Invalid search query parameter
  • max_uses_exceeded: Maximum web search tool uses exceeded
  • query_too_long: Query exceeds maximum length
  • unavailable: An internal error occurred

Next steps

Handle responses where Haijun calls several tools in a single turn.

Let the SDK manage the tool_use loop, result formatting, and retries for you.

Write schemas and descriptions that steer Haijun toward the right tool.

On this page
Handling results from client toolsExample API response with a tool_use content blockHandling results from server toolsHandling errors with is\_errorNext steps