On this page
Guides / Run Mets (Runs)

Run Mets (Runs)

Run your workspace's Met from the API, with optional memory, and read the result.

Updated View .md

A Run is one execution of your workspace's Met over an input. It is the core of agentic infrastructure as a service: the same Met that answers in the chat, now triggered by your code.

A basic run

const run = await met.runs.create({ input: 'Summarize the leads from today' });

console.log(run.status);  // 'completed'
console.log(run.output);  // what the Met produced
run = met.runs.create("Summarize the leads from today")

print(run["status"])  # 'completed'
print(run["output"])  # what the Met produced
curl -X POST https://api.met.meteor.com.co/api/v1/workspaces/7/runs \
  -H "Authorization: Bearer $MET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":"Summarize the leads from today"}'

The request is POST /workspaces/:id/runs. The response is a run resource with an opaque id (run_…), status, output, livemode and metadata.

Pick the Met (deterministic bind)

Pass met — the name or id of a Met in the workspace — to run that Met directly, with its Functions and tools, skipping the orchestrator:

await met.runs.create({ met: 'Valeria', input: 'How many leads did I close?' });
met.runs.create("How many leads did I close?", met="Valeria")

Names resolve case-insensitively: exact match first, then prefix. If you omit met, the workspace orchestrator routes to the right Met, exactly as it does in the chat.

Routing is AI work too: without met, the main Met reads the request and can delegate it to another Met, and each one is an execution with its own cost. If you already know which Met has to answer, pass it: the Run goes straight to that Met, without the orchestrator's round trip.

Memory: conversations

Without a conversation_id, the run happens in an ephemeral conversation with no prior memory. To give it continuity, pass an existing conversation:

await met.runs.create({ input: 'And last month?', conversation_id: 1234 });

With a conversation_id, the first met you send becomes the conversation default: later runs that omit met use that same Met. An explicit met always wins over the default.

Vision: images and files

Pass attachments in attachments so the Met can see an image or read a document, with automatic OCR for text inside an image:

await met.runs.create({
  met: 'Valeria',
  input: 'Does the installed sign match the approved design?',
  attachments: [{ url: 'https://…/photo.jpg', kind: 'image' }],
});

Each attachment is { url, mime_type?, name?, kind? }, where kind is image · document · audio · video · file. A bare URL inside input is not seen — it has to go in attachments.

Isolated Run: no tools, no context

To extract or classify something from a text or a document, you do not need a Met with all its tools. With tool_policy: "none", the Run works only with the input, its attachments and the instructions of the Met you pick:

const caps = await met.runs.capabilities();
if (caps.tool_policies.includes('none')) {
  const run = await met.runs.create({
    met: 'Extractor',
    tool_policy: 'none',
    input: 'Return the tax ID and the total of this invoice as JSON: ...',
  });
  if (run.status === 'completed') console.log(run.output);
}
caps = met.runs.capabilities()
if "none" in caps["tool_policies"]:
    run = met.runs.create(
        "Return the tax ID and the total of this invoice as JSON: ...",
        met="Extractor",
        tool_policy="none",
    )
    if run["status"] == "completed":
        print(run["output"])
curl -X POST https://api.met.meteor.com.co/api/v1/workspaces/7/runs \
  -H "Authorization: Bearer $MET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"met":"Extractor","tool_policy":"none","input":"Return the tax ID and the total of this invoice as JSON: ..."}'

What changes compared with a normal Run:

GET /workspaces/{workspaceId}/runs/capabilities (met.runs.capabilities()) tells you whether the policy is available; it needs runs:execute and spends no Energy. The isolated Run is billed like any Run, but without the context it did not need. When it beats a flow or a full Met: Architecture: when a flow, when a Met.

Read runs

const run = await met.runs.retrieve('run_01J8…');   // status + output

for await (const r of met.runs.iterate()) {           // full history
  console.log(r.id, r.status);
}
run = met.runs.retrieve("run_01J8…")   # status + output

for r in met.runs.iterate():           # full history
    print(r["id"], r["status"])

iterate() walks every page for you — see Errors and pagination.

If you need to wait for a run to finish, use met.runs.wait(id) (in Python, met.runs.wait(run_id)) instead of calling retrieve() in a loop: it asks less and less often, waits for whatever Retry-After says if it gets a 429, and gives up after 5 minutes with MetWaitTimeoutError. Better yet, subscribe to the run.completed and run.failed webhooks and let us tell you.

Cost

Every run debits Energy through the usual ledger, marked execution_type='api' and attributed to the key. In your dashboard, API usage is reported separately from the internal chat.

Want the result as it is generated? See the Streaming guide.