BashBrainTeammatesPricingDevelopersGet a test key

init

Start a new agent by describing its job in plain words. Bash, the AI agent Vestra runs for you, asks you a few short questions. Then it writes the first draft of your deployment, with starter tests. A deployment is your agent's setup: its instructions, the tools it may use and its limits. The questions arrive in a conversation, like any other reply from Bash.

Describe the job

Say in plain words what the agent should do, and for whom.

TypeScript
const draft = vestra.init({  for: 'customers',  describe: 'Help Tripnest travellers fix broken trips: cancellations, delays, missed connections. Look bookings up with get_booking.',});

Answer its questions

Bash asks a few short questions, then writes vestra.yaml with starter tests.

TypeScript
for await (const question of draft.questions()) await question.answer(await prompt(question.text));

Save the draft to your repo

Publish it with deploy when you are ready.

TypeScript
await writeFile('vestra.yaml', await draft.yaml());

Read the closing words

They say what the draft sets up, the tools your code must answer, the tests it wrote, and the next steps.

TypeScript
const closing = await draft.closing();for (const tool of closing?.tools ?? []) console.log(`Your code answers ${tool.name}: ${tool.description}`);closing?.next_steps.forEach((step, n) => console.log(`${n + 1}. ${step}`));

Describe the job

Say in plain words what the agent should do, and for whom.

Python
draft = vestra.init(    "Help Tripnest travellers fix broken trips: cancellations, delays, missed connections. Look bookings up with get_booking.",    for_="customers",)

Answer its questions

Bash asks a few short questions, then writes vestra.yaml with starter tests.

Python
for question in draft.questions():    question.answer(input(question.text + " "))

Save the draft to your repo

Publish it with deploy when you are ready.

Python
with open("vestra.yaml", "w") as file:    file.write(draft.yaml())

Read the closing words

They say what the draft sets up, the tools your code must answer, the tests it wrote, and the next steps.

Python
closing = draft.closing()for tool in closing.tools if closing else []:    print(f"Your code answers {tool.name}: {tool.description}")for n, step in enumerate(closing.next_steps if closing else [], 1):    print(f"{n}. {step}")

Describe the job

Bash asks a few short questions here in the terminal, then writes vestra.yaml with starter tests. It ends with its closing words: the tools your code must answer, and the next steps.

CLI
vestra init "Help Tripnest travellers fix broken trips: cancellations, delays, missed connections. Look bookings up with get_booking." --for customers

Run init from a script or CI

Pass your answers as text, from a file or from stdin (-), so nobody needs to be at the terminal. --json prints the file's path and the closing words as JSON.

CLI
vestra init "Help Tripnest travellers fix broken trips: cancellations, delays, missed connections." \  --answers answers.txt --force --json

Describe the job

The interview runs as a conversation, so its questions arrive like any other reply.

HTTP
curl "$VESTRA_BASE_URL/v1/deployments/interview" \  -H "Authorization: Bearer $VESTRA_API_KEY" \  -H "Content-Type: application/json" \  -d '{ "name": "Trip rescue", "slug": "trip-rescue", "job": "Help Tripnest travellers fix broken trips: cancellations, delays, missed connections. Look bookings up with get_booking." }'

Answer its questions

Follow the conversation the response names, and reply in it.

HTTP
curl -N "$VESTRA_BASE_URL/v1/conversations/conv_iv7/events" \  -H "Authorization: Bearer $VESTRA_API_KEY" curl "$VESTRA_BASE_URL/v1/conversations/conv_iv7/messages" \  -H "Authorization: Bearer $VESTRA_API_KEY" \  -H "Content-Type: application/json" \  -d '{ "message": "Ask first before paying a fare difference." }'

Save the draft to your repo

When the interview ends, download the draft as vestra.yaml, starter tests included.

HTTP
curl "$VESTRA_BASE_URL/v1/deployments/trip-rescue?format=yaml" \  -H "Authorization: Bearer $VESTRA_API_KEY" \  -o vestra.yaml

Read the closing words

The draft version (the deployment's draft_version) has them in its interview field: what it set up, the tools your code must answer, the spending cap per task, the tests, and the next steps.

HTTP
curl "$VESTRA_BASE_URL/v1/deployments/trip-rescue/versions/2" \  -H "Authorization: Bearer $VESTRA_API_KEY"
MCP
{  "method": "tools/call",  "params": {    "name": "init",    "arguments": {      "describe": "Help Tripnest travellers fix broken trips: cancellations, delays, missed connections. Look bookings up with get_booking.",      "for": "customers"    }  }}

Good to know

What you get at the end

The draft becomes the deployment's next version, with its starter tests. The interview ends with its closing words: what the draft sets Bash up to do, the tools your code must answer, the spending cap per task, how many tests it wrote, and the next steps. The CLI prints them. You can also read them with draft.closing() in an SDK, or in the version's interview field over HTTP and MCP.

GET /v1/deployments/{name}?format=yaml returns the draft as vestra.yaml, ready to keep in your repo and publish with deploy. After you edit the file, vestra test saves your edit as a new version and tests it, without promoting it. vestra deploy then promotes it, which makes it the version your agent runs, without running the tests again.

Your own tools

When the job mentions one of your own tools, the file declares it: its name, what it does, its input and what it returns. Vestra never writes the tool's code. Your code runs the tool, with vestra dev --tools ./tools.mjs or with the SDK's tools option.

The interview asks what each tool returns. Answer with one example result that uses your code's own field names and value formats, with made-up values. Never paste a real record. For example: {customer: 'Maya Chen', due_back: '2026-10-04 18:00'}. The tool's description keeps this example. Each starter test that calls the tool gets tool_results copied from it, with no field, unit or time zone the example lacks. That way test can play the tool before your code exists, and answer the way your code will.

Some tools need your user's approval before they run. Such a tool also takes, as inputs, each value the user agrees to, such as charge_usd and new_due_back on extend_rental. The instructions say where each value comes from, such as daily_price_usd from get_rental. The approval shows every input, so the user always sees the price before saying yes. If none of your lookups returns such a value (because your code works out the price only as it acts), the interview asks for a tool that does, such as a quote, and marks it read_only. Bash never guesses a value for an approval. The closing words remind you that your code must check these values against its own before it acts.

Running init from a script or CI

With --answers, vestra init reads your answers as text instead of asking at the terminal. Use it from a coding agent or CI: vestra init "<the job>" --answers answers.txt, or --answers - to read them from stdin. If the interview asks a question after your answers run out, it is told to use the defaults. The draft holds only the rules your answers give, so include every rule the job needs. Init adds one rule without asking, which you can edit: how Bash checks who is asking before it shares a user's record.

Who the agent works for

Say in the job description whether this agent works for your users, inside your product, or for your own company. The interview runs in a conversation of its own, kept apart from your company's own Bash and its memory.

The routes behind init1 route, each with every field in the API reference
POST/v1/deployments/interviewBuild a deployment by talking to Bash: describe the job, answer its questions, receive a draft version.Key scope: setup (or all)