Skip to content

Start typing to search the documentation.

Tools

Last updated View as Markdown

Tools let an agent retrieve information or perform actions while it works. Define tools when an agent needs to call your application’s data layer or services, such as looking up an order, creating a ticket, or approving a request.

A skill provides reusable instructions; a tool executes application code. File and command access in an agent’s workspace comes from its configured sandbox rather than from a custom application tool.

Custom tools

Use defineTool(...) to create a new tool for your agent:

import { Type, defineTool } from '@flue/runtime';

const orderStatuses = new Map([
  ['order_1042', 'packed'],
  ['order_1043', 'shipped'],
]);

export const lookupOrderStatus = defineTool({
  name: 'lookup_order_status',
  description: 'Look up the current fulfillment status for one order ID.',
  parameters: Type.Object({
    orderId: Type.String({ description: 'Order ID in the form order_1234' }),
  }),
  execute: async ({ orderId }) => {
    const status = orderStatuses.get(String(orderId));
    return status ?? 'No order was found.';
  },
});

A custom tool has four parts:

  • name is the model-facing name used to call the tool.
  • description helps the model decide when the capability is appropriate.
  • parameters describes the inputs the model may supply. For authored tools, build this schema with Type from @flue/runtime.
  • execute performs the application-controlled work and returns text for the model to use in its response.

Use clear action-oriented names, such as lookup_order_status or create_support_ticket. Tools available during the same operation must have distinct names.

Using tools

Provide a stable capability in the configuration for the agent that needs it:

import { createAgent } from '@flue/runtime';
import { lookupOrderStatus } from '../shared/order-tools.ts';

export default createAgent(() => ({
  model: 'anthropic/claude-haiku-4-5',
  instructions: 'Help customers check the status of their orders.',
  tools: [lookupOrderStatus],
}));

When this agent receives a request, the model can call lookup_order_status if it needs the current status before composing its answer. The call and returned text become part of the session context so the agent can continue working with the result.

Attach tools this way when they are part of an agent’s ordinary capabilities. When a tool is needed for only one bounded action, you can instead provide it in the options for session.prompt(...), session.skill(...), or session.task(...); see the Agent API.

Protect access

A tool’s parameters are model-selected inputs, not an authorization boundary. Your application should decide which customer, account, repository, or credential a tool can use, then let the model select only values within that boundary.

For an addressable customer-support agent, the selected agent instance can establish which customer’s orders are accessible:

import { Type, createAgent, defineTool } from '@flue/runtime';
import { orders } from '../shared/orders.ts';

export default createAgent(({ id: customerId }) => ({
  model: 'anthropic/claude-haiku-4-5',
  tools: [
    defineTool({
      name: 'lookup_customer_order',
      description: 'Look up one order belonging to this customer.',
      parameters: Type.Object({
        orderId: Type.String(),
      }),
      execute: async ({ orderId }) => {
        if (typeof orderId !== 'string') throw new Error('An order ID is required.');
        const status = await orders.getStatus(customerId, orderId);
        return status ?? 'No accessible order was found.';
      },
    }),
  ],
}));

In this example, the model may choose an order ID to look up, but it cannot choose the customer used in the query. Your route must still authenticate the caller and ensure that they may access the selected agent id; see Agents and Routing.

The same principle applies in workflows. When a workflow establishes the authorized resource or credential for one invocation, it can provide the bounded tool while initializing its agent:

const lookupCustomerOrder = defineTool({
  name: 'lookup_customer_order',
  description: 'Look up one order belonging to the authenticated customer.',
  parameters: Type.Object({ orderId: Type.String() }),
  execute: async ({ orderId }) => {
    const status = await orders.getStatus(customer.id, String(orderId));
    return status ?? 'No accessible order was found.';
  },
});

const harness = await init(agent, { tools: [lookupCustomerOrder] });

Do not put credentials, tenant identifiers, or unrestricted destinations into model-selected tool arguments when trusted application code can supply them instead.

Connect MCP servers

An MCP server supplies remotely implemented tools. connectMcpServer(...) lists those tools and returns ordinary tool definitions, which you provide to agent work in the same way as your own custom tools.

import { connectMcpServer, createAgent, type FlueContext } from '@flue/runtime';

type Env = {
  INVENTORY_MCP_URL: string;
  INVENTORY_MCP_TOKEN: string;
};

const agent = createAgent(() => ({
  model: 'anthropic/claude-haiku-4-5',
}));

export async function run({ init, payload, env }: FlueContext<{ question: string }, Env>) {
  const inventory = await connectMcpServer('inventory', {
    url: env.INVENTORY_MCP_URL,
    headers: {
      Authorization: `Bearer ${env.INVENTORY_MCP_TOKEN}`,
    },
  });

  try {
    const harness = await init(agent, { tools: inventory.tools });
    const session = await harness.session();
    return await session.prompt(payload.question);
  } finally {
    await inventory.close();
  }
}

Provide MCP credentials and connection settings from trusted application code, then close the connection when the work using its tools finishes. Flue prefixes each MCP tool’s model-facing name with its connection name; for example, lookup_item from this server becomes mcp__inventory__lookup_item.

Next steps

  • Agents — configure continuing agents that use tools.
  • Workflows — initialize agent work with invocation-specific tools.
  • Skills — add reusable instructions that may direct an agent to use its tools.
  • Sandboxes — control the workspace and command boundary available to agent work.
  • Agent API — look up operation options, including tools supplied for one call.