# How to build an AI agent

An **AI agent** is a program that takes an instruction in natural language, decides which tools to use to carry it out, runs them and answers. What separates it from a normal integration with a language model is the word *decides*: nobody wrote the sequence of steps up front.

In Meteor an agent is called a **Met**, and it is three things: a **prompt** that defines what it does, a set of **tools** it can use, and **access to** the business's **data**. The language model is the fourth component and the most interchangeable one — it is not what determines whether the agent is any good.

## Agent or flow: the decision to make first

It is the most expensive confusion, because you pay for it in production and not in development.

| | agent | flow |
|---|---|---|
| decides the sequence | the model, on every execution | you, when you build it |
| good for | what cannot be foreseen | what cannot be improvised |
| example | answering a question nobody anticipated | charging, dispatching, notifying |
| fails by | answering something reasonable but wrong | freezing in the face of the unexpected |

The right answer is almost never one of the two: **the agent handles the conversation and calls a flow when something has to be executed that admits no improvisation.** An agent that charges a customer while deciding the amount is an incident waiting its turn; a flow that tries to handle a complaint is a form in disguise.

In Meteor both exist and they call each other — a Met can trigger a flow as one of its tools.

## The five steps

### 1. Get an API key

From the panel, under Settings → Developers. Start with a test key (`met_test_`): it runs for free, with a daily cap, and the scopes that produce real side effects stay restricted — there is no way to message a real customer by accident.

```bash
npm install @meteor.ia/sdk
```

Full detail in [Authentication](authentication.html).

### 2. Define what the agent does

The prompt is the agent's definition, not decoration. What decides quality is not its length but its precision about **what it must not do** and **when to hand over to a human**.

A Met is created from the panel or over the API, and that is where you assign its capabilities. See [Mets and their tools](mets-and-tools.html).

### 3. Give it access to the business data

An agent without data improvises. In Meteor data lives in **collections** — workspace tables the agent reads and writes without you programming an endpoint for each one:

```ts
import Met from '@meteor.ia/sdk';
const met = new Met(process.env.MET_API_KEY!, { workspaceId: 7 });

const cols = await met.collections.list();
await met.items.create(cols[0].id, { data: { titulo: 'New enquiry' } });
```

If the data lives in another system, you connect it as [MCP integrations](mcp-integrations.html) and the agent uses them as tools.

### 4. Run it

```ts
const run = await met.runs.create({ input: "Summarize today's enquiries" });
console.log(run.output);
```

With `stream: true` the answer arrives token by token over SSE, which is what you want in a chat interface. See [Run Mets](run-mets.html) and [Streaming](streaming.html).

### 5. Connect it to a channel

An agent that only answers over the API is not serving anyone. By connecting WhatsApp, Messenger or Instagram to the workspace, the Met replies in the contact's thread:

```ts
await met.contacts.sendMessage(42, 'The visit is booked');
```

There is a limit here worth knowing **before** you write code: outside the 24-hour window since the person's last message, WhatsApp only allows writing with **templates approved by Meta**. It is not a Meteor limit and it cannot be worked around. See [CRM and contacts](contacts.html).

## What almost always gets forgotten

**An agent needs to be able to give up.** The case that decides whether people write to it again is not the one it resolves well, but the one it cannot resolve: if there is no way out to a human, the conversation dies there. In Meteor that is autopilot — it pauses for a few minutes and resumes on its own, instead of switching off until somebody remembers. See [Workspace operations](workspace-operations.html).

**Executions are billed, so you have to be able to look at them.** `GET /billing/executions` gives one row per execution with its cost. When the total doesn't add up, the answer is almost always an agent calling itself in a loop.

**Everything an agent did stays auditable.** Every execution has its trace, and the `request_id` of the HTTP response ties it to what you see in the panel. See [Live events](events.html).

## Using Meteor from your own agent

If you already have an agent — in Claude, in Cursor, or one of your own — you don't need the API: Meteor exposes a **remote MCP server** with 22 `met_*` tools. Your agent runs Mets, queries the CRM, triggers tasks and reads data as native tools:

```
https://api.met.meteor.com.co/api/v1/mcp
```

The catalog is filtered by your API key's scopes: a tool whose scope you don't have simply does not appear. See [MCP server](../../mcp.html).

## Frequently asked questions

### Do I need to train a model?

No. An agent is defined by prompt, tools and data; the model is an interchangeable component. Training makes sense when the problem is that the model doesn't *know* something about the domain, and almost always the real problem is that it *can't do* something — and that is fixed with a tool, not with training.

### How long does it take to get one working?

A Met answering with access to a collection is a few hours. What takes time is the rest: defining when it gives up, what it must not say, and what happens when the tool it needs is down.

### Can I test without touching real data?

Yes, with a `met_test_` key. Executions come out with `livemode: false` and debit no Energy.

### Which languages have an SDK?

TypeScript (`@meteor.ia/sdk`) and Python (`meteor-ia`), both with full parity over the 300 public operations. There is also a CLI (`met`) and the REST API with its published OpenAPI.

### What if my case isn't conversational?

A good part of what people build is not a chat: it is a procedure that runs on its own. Those are [tasks](tasks.html) — they fire over the API, on a schedule or on an event, and their steps can run Mets.
