Skip to content

Start a run

Terminal window
kindgi runs start --flow=acme.review-order --input='{"orderId":"A-200"}'
kindgi runs start --flow=acme.review-order --input=@order.json

--input is the run's input as JSON, or @ and a file to read it from. The command waits for the run to finish and prints it. With --no-wait, it prints the run as soon as it exists:

Terminal window
kindgi runs start --flow=acme.reserve-order --input='{"orderId":"A-300"}' --no-wait
{
"id": "1b1f6486-3faf-4ab7-8506-c09f50f989bc",
…
"flowId": "acme.reserve-order",
"flowVersion": "0.1.0",
"status": "pending",
"dryRun": false,
…
}

kindgi runs get <run-id> shows it again, with its output once it's done.

Create a client. With no arguments it reads the API's URL and a token from KINDGI_API_URL and KINDGI_API_TOKEN, which you set in your env file (.env / .env.local). In development, when they aren't set, it uses the running kindgi dev, which writes both to .kindgirc.json, and warns once that you should set them. In production (NODE_ENV or KINDGI_ENV set to production) it never does, so set them there.

import { createClient } from '@kindgi/sdk/client';
const kindgi = createClient(); // KINDGI_API_URL, KINDGI_API_TOKEN, or the running kindgi dev
const run = await kindgi.runs.start({
flow: 'acme.review-order',
input: { orderId: 'A-200' },
});
console.log(run.status, run.output);
completed { status: 'held', orderId: 'A-200' }

start returns when the run completes, fails or waits for something (a person's approval, for example: status is then suspended). Use it when the run is short and the caller needs the answer.

With wait: false, start returns as soon as the run exists, with status pending, and the run finishes on the server:

let run = await kindgi.runs.start({
flow: 'acme.reserve-order',
input: { orderId: 'A-300' },
options: { wait: false },
});
console.log(run.id, run.status);
while (run.status === 'pending' || run.status === 'running') {
await new Promise((resolve) => setTimeout(resolve, 1000));
run = await kindgi.runs.get(run.id);
}
console.log(run.status, run.output);
dbcf7457-0d25-49b9-9112-b03c9b44e9e8 pending
completed { attempt: 3, orderId: 'A-300', reserved: true }

Polling works, but there are better ways to learn that a run ended: follow its events, or have Kindgi send your app a webhook when it finishes.

Agent runs take options: { wait: false } too: the turn then runs in the background. Start an agent with agent instead of flow, and its input ({ "userMessage": "…" }, see Give an agent its input).

Field
id The run's id: for get, cancel, the journal and the event stream.
status pending, running, suspended, completed, failed or cancelled.
output What the run returned, once it completed.
failureMessage Why it failed.
flowId, flowVersion The flow and the version the run is pinned to. An agent's turn reports agent.turn.
dryRun Whether it was a dry run.
publicAccessToken A read-only token for this run, for a browser, when the deployment issues them (details). Only start returns it.

The client references have every field and option: TypeScript, Python, and the CLI.

A run that fails is still a run: start returns it, with status: "failed" and failureMessage. A request the API refuses (a flow that doesn't exist, a malformed input) raises an error instead, and no run exists:

import { KindgiApiError } from '@kindgi/sdk/client';
const run = await kindgi.runs.start({ flow: 'acme.review-order', input: { orderId: 'Z-9' } });
if (run.status === 'failed') console.log(run.failureMessage);
try {
await kindgi.runs.start({ flow: 'acme.no-such-flow', input: {} });
} catch (err) {
if (err instanceof KindgiApiError) console.log(err.error.code, err.message);
}
handler-error: Tool "acme.get-order" handler threw: handler-throw: Handler for tool "acme.get-order" threw: Error: No order Z-9
not-found No flow "acme.no-such-flow" is registered in this tenant.

A request that times out on your side may have started the run anyway. Retry a start safely shows how to retry without starting it twice.