> ## Documentation Index
> Fetch the complete documentation index at: https://docs.os.meetluno.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent tools

> Let agents call your actions as tools.

An [agent](https://docs.os.meetluno.ai/learn/agents/overview.md) decides what to do at runtime. To give it reliable capabilities, you attach [actions](https://docs.os.meetluno.ai/learn/actions/overview.md) as tools. Each action becomes a tool the model can call with a typed argument, and Luno OS validates the input, runs the action, and returns the result to the agent.

## Attach an action as a tool

Pass action definitions in the `tools` array of `defineAgent()`. The same action you'd use as a workflow step works here, unchanged.

```ts src/agents/support.ts theme={null}
import { defineAgent } from "@meetluno/luno/agent";
import { triage } from "../actions/triage";

export default defineAgent({
  slug: "support",
  name: "Support",
  description: "Helps customers using the triage tool.",
  systemPrompt: "Help customers. Use the triage tool to classify incoming messages.",
  model: "openai/gpt-5.6-sol",
  tools: [triage],
});
```

When the agent calls the tool, Luno OS parses the model's arguments against the action's `input` schema, runs `run`, and returns the `output` as the tool result.

## How an action maps to a tool

The action's metadata becomes the tool the model sees:

| Tool field | Comes from |
| - | - |
| **Name** | The action `slug` |
| **Label** | The action `name` |
| **Description** | The action `description` |
| **Parameters** | The action `input` Zod schema |

Because the model reads `description` to decide when to call a tool, give tool actions a clear, action-oriented `description`. The `output` schema shapes what the agent gets back.

## Design tool actions for the model

A tool action is read by the model, so write it for that audience:

* **Write a clear `description`.** The model uses it to decide *when* to call the tool. Say what it does and when to reach for it, in plain language.
* **Describe each input field.** Add `.describe()` to the fields in the `input` schema. The schema becomes the tool's parameters, so the descriptions tell the model what each argument means.
* **Keep the output lean.** The action's `output` is serialized to JSON and returned to the model as the tool result, so it counts against the context window. Return the fields the agent needs to act on, not entire upstream payloads.

```ts src/actions/lookup-customer.ts theme={null}
export const lookupCustomer = defineAction({
  slug: "lookup-customer",
  name: "Lookup customer",
  description: "Look up a customer by email. Use before answering billing questions.",
  input: z.object({
    email: z.string().email().describe("The customer's email address"),
  }),
  output: z.object({
    plan: z.enum(["free", "pro", "enterprise"]),
    openInvoices: z.number(),
  }),
  run: async (input) => lookup(input.email),
});
```

## Credentials for tool actions

When an action declares `credentials`, Luno OS resolves them before the tool runs; the agent never sees the secret. If an action can resolve credentials at more than one [scope](https://docs.os.meetluno.ai/learn/credentials/overview.md) (organization, project, or user), pin the scope with `.scope()` when attaching it:

```ts theme={null}
export default defineAgent({
  slug: "support",
  name: "Support",
  description: "Looks up customers with the requesting user's credentials.",
  systemPrompt: "Look up customers on behalf of the requesting user.",
  model: "anthropic/claude-sonnet-5",
  tools: [lookupCustomer.scope("user")],
});
```

Without an explicit scope, the resolver tries the project default, then the organization default. For `.scope("user")`, also [assign a user credential](https://docs.os.meetluno.ai/learn/credentials/connect-credentials.md#bind-a-credential-to-a-step-tool-or-poll-action) to that tool — user scope is not inferred from the run. See [credentials](https://docs.os.meetluno.ai/learn/credentials/overview.md) for how scopes and connections work.

## Beyond actions

Actions are the usual way to give an agent reliable capabilities, but `tools` also accepts other tool types: MCP tools, subagents, and workflows — import them directly into `tools` (no wrappers). See [build agents](https://docs.os.meetluno.ai/learn/agents/build-agents.md) for subagents and workflows as tools.

Agents can call these same tools from JavaScript or TypeScript when they need to compose several
calls or process results in a loop. See [code mode](https://docs.os.meetluno.ai/learn/agents/build-agents.md#code-mode).

## Next steps

> **[Actions as workflow steps](https://docs.os.meetluno.ai/learn/actions/workflow-steps.md)**
>
> Run the same actions as durable steps in a workflow.

> **[Build agents](https://docs.os.meetluno.ai/learn/agents/build-agents.md)**
>
> Configure tools, models, skills, files, and more.

> **[Credentials](https://docs.os.meetluno.ai/learn/credentials/overview.md)**
>
> Declare and scope the credentials a tool action needs.

> **[Integrations](https://docs.os.meetluno.ai/integrations.md)**
>
> Browse built-in integration actions to attach as tools.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.