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

# Tools & actions

> Give an agent callable operations — your tools, connector actions, sub-agents, and MCP servers — on defineAgent.

Actions transform your agent from a reasoning engine into an action-taker. In code, you give an agent four kinds of callable capability on `defineAgent`:

```ts agents/sdr.ts theme={null}
export const sdr = defineAgent("sdr", {
  connector: openai,
  languageModel: "gpt-4o",
  systemPrompt: "Qualify inbound leads and route hot ones to Slack.",

  // Your own tools (defineTool handles)
  tools: [enrich, { ref: scoreLead, description: "Score ICP fit 1–10.", isBulkAllowed: true }],

  // Actions from a connected integration
  connectorActions: [{ integration: "hunter", actionSlug: "findEmail" }],

  // Specialist agents this one can delegate to
  subAgents: [{ ref: researcher, waitUntilFinished: true }],

  // External MCP servers whose tools the agent can call
  mcpClients: [{ kind: "custom", name: "notion", url: "https://mcp.notion.com/mcp", authentication: null, disabledToolSlugs: [] }],
});
```

`tools`, `connectorActions`, and `subAgents` all accept the same per-call options — `{ name, description, isBulkAllowed, waitUntilFinished }` — wrapped around a bare handle (`{ ref, …options }`) or, for connector actions, alongside `integration` / `actionSlug`. The `description` is the AI contract — the agent reads it to decide when to call the action.

<Note>
  Connect an integration with [`defineConnector`](/connectors/overview) before
  referencing its actions, and see [Tools](/tools/overview) for building the
  tools you pass in. Run [`cargo-ai cdk types`](/get-started/project-layout) so
  `actionSlug` values autocomplete from the real registry.
</Note>

## How actions work

When an agent receives a task, it:

1. **Analyzes** the goal and available actions
2. **Selects** the appropriate action(s) based on their descriptions
3. **Executes** the action with the right inputs
4. **Uses the output** to continue reasoning or complete the task

<Note>
  The action's **description** is critical. The agent reads this description to
  decide when and how to use the action. Write descriptions that clearly explain
  what the action does and when to use it.
</Note>

***

## Configuring an action

### Description (the AI contract)

This plain-language description tells the agent:

* **What** the action does
* **When** to use it
* **What inputs** it expects

**Good example:**

```
"Enriches a company using its domain. Returns firmographic data including
employee count, industry, funding, and tech stack. Use this when you need
company information for qualification or research."
```

**Poor example:**

```
"Gets company data"
```

### Fixed vs. agent-decided inputs

By default the agent decides every input field of a connector action at runtime, from conversation context and the action's description. To lock a field to a fixed value, set it in the action's `config` — anything you put there is sent as-is and never left to the agent:

```ts theme={null}
connectorActions: [{
  integration: "hubspot",
  actionSlug: "createRecords",
  config: { objectType: "deals" },   // always deals — the agent fills in the rest
}],
```

<Tip>
  Mix fixed and agent-decided fields when some inputs should always be the same
  (e.g., a specific CRM pipeline ID) while others depend on the conversation
  context (e.g., a lead's email address).
</Tip>

In the UI, each field additionally has a mode selector — **Default** (fixed value), **Auto** (agent decides), or **Disable** (field skipped entirely). Disabling a field is UI-only today; in code, fields are either fixed via `config` or agent-decided.

### Bulk execution

Set `isBulkAllowed: true` when the agent should apply the action across multiple records in a single run. Useful for batch operations like:

* Enriching a list of companies
* Updating multiple CRM records
* Sending notifications to several recipients

### Waiting for completion

`waitUntilFinished` (default `true`) blocks the agent until the action finishes so it can use the result. Set it to `false` for fire-and-forget calls — e.g. a Slack notification the agent doesn't need to read back.

***

## Common action types

| Category          | Examples                     | Typical use                            |
| :---------------- | :--------------------------- | :------------------------------------- |
| **Enrichment**    | Clearbit, Apollo, FullEnrich | Gather company or contact data         |
| **CRM**           | Salesforce, HubSpot, Attio   | Create/update records, log activities  |
| **Communication** | Slack, Email, Outreach       | Send messages, add to sequences        |
| **Data lookup**   | Internal APIs, SQL queries   | Retrieve custom data from your systems |

***

## MCP servers

Cargo agents support the **Model Context Protocol (MCP)** — an open standard for connecting AI models to external actions and data sources. Declare the servers an agent can call with `mcpClients`; Cargo discovers and registers their tools automatically:

```ts theme={null}
mcpClients: [
  // Any MCP-compatible server, by URL
  { kind: "custom", name: "notion", url: "https://mcp.notion.com/mcp", authentication: null, disabledToolSlugs: [] },

  // An MCP server backed by one of your connectors (by uuid)
  { kind: "connector", name: "hubspot", connectorUuid: "9c26…", integrationSlug: "hubspotMcp", disabledToolSlugs: [] },
],
```

Use `disabledToolSlugs` to hide individual tools from the agent, and `authentication` to pass an OAuth token set for servers that require one (or `null` for unauthenticated servers). In the UI, the same thing is configured by pasting the server URL on the agent's Actions tab.

<Note>
  This is the agent **consuming** external MCP servers. To expose your own
  Cargo tools and agents *as* an MCP server, see
  [MCP servers](/mcp-servers/overview).
</Note>

***

## Best practices

<CardGroup cols={2}>
  <Card title="Write clear descriptions">
    The agent relies on descriptions to choose actions. Be specific about what the
    action does and what it returns.
  </Card>

  <Card title="Name actions descriptively">
    Use names like `Enrich-Company` or `Slack-Notify-Rep` instead of generic
    names like `Action1`.
  </Card>

  <Card title="Handle failures gracefully">
    In your agent's instructions, specify what to do if an action call fails
    (retry, skip, report error).
  </Card>

  <Card title="Limit scope">
    Only give agents access to the actions they need. Fewer actions = faster, more
    accurate action selection.
  </Card>
</CardGroup>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Connectors" icon="plug" href="/connectors/overview">
    Connect integrations with defineConnector before referencing their actions.
  </Card>

  <Card title="Tools" icon="wrench" href="/tools/overview">
    Build reusable tools with defineTool to pass into an agent.
  </Card>
</CardGroup>
