How to build an AI agent
What an agent is, how it differs from a flow-based chatbot, and the five steps to having one answering on WhatsApp with access to your business data.
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.
npm install @meteor.ia/sdk
Full detail in Authentication.
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.
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:
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 and the agent uses them as tools.
4. Run it
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 and Streaming.
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:
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.
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.
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.
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.
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 — they fire over the API, on a schedule or on an event, and their steps can run Mets.