---
description: Give agents application capabilities through custom tools and MCP servers.
---

# Tools

Last updated May 29, 2026 [ View as Markdown](https://flueframework.com/docs/guide/tools/index.md) 

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](https://flueframework.com/docs/guide/skills/) provides reusable instructions; a tool executes application code. File and command access in an agent’s workspace comes from its configured [sandbox](https://flueframework.com/docs/guide/sandboxes/) 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](https://flueframework.com/docs/api/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](https://flueframework.com/docs/guide/building-agents/) and [Routing](https://flueframework.com/docs/guide/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](https://flueframework.com/docs/guide/building-agents/) — configure continuing agents that use tools.
* [Workflows](https://flueframework.com/docs/guide/workflows/) — initialize agent work with invocation-specific tools.
* [Skills](https://flueframework.com/docs/guide/skills/) — add reusable instructions that may direct an agent to use its tools.
* [Sandboxes](https://flueframework.com/docs/guide/sandboxes/) — control the workspace and command boundary available to agent work.
* [Agent API](https://flueframework.com/docs/api/agent-api/) — look up operation options, including tools supplied for one call.

## Docs Navigation

Current page: [Tools](https://flueframework.com/docs/guide/tools/)

### Sections

* [Guide](https://flueframework.com/docs/getting-started/quickstart/)
* [Reference](https://flueframework.com/docs/api/agent-api/)
* [CLI](https://flueframework.com/docs/cli/overview/)
* [SDK](https://flueframework.com/docs/sdk/overview/)
* [Ecosystem](https://flueframework.com/docs/ecosystem/overview/)

### Introduction

* [ Getting Started ](https://flueframework.com/docs/getting-started/quickstart/)
* [ What is an agent? ](https://flueframework.com/docs/concepts/agents/)
* [ Why Flue? ](https://flueframework.com/docs/introduction/why-flue/)
* [ Changelog ](https://github.com/withastro/flue/blob/main/CHANGELOG.md)

### Guides

* [ Project Layout ](https://flueframework.com/docs/guide/project-layout/)
* [ Models & Providers ](https://flueframework.com/docs/guide/models/)
* [ Agents ](https://flueframework.com/docs/guide/building-agents/)
* [ Workflows ](https://flueframework.com/docs/guide/workflows/)
* [ Skills ](https://flueframework.com/docs/guide/skills/)
* [ Tools ](https://flueframework.com/docs/guide/tools/)
* [ Subagents ](https://flueframework.com/docs/guide/subagents/)
* [ Sandboxes ](https://flueframework.com/docs/guide/sandboxes/)
* [ Routing ](https://flueframework.com/docs/guide/routing/)
* [ Develop & Build ](https://flueframework.com/docs/guide/develop-and-build/)
* [ Chat ](https://flueframework.com/docs/guide/chat/)
* [ Observability ](https://flueframework.com/docs/guide/observability/)