ask
Send a job in plain words to Bash, the AI agent Vestra runs for you. The job can be for one of your users, for many users at once, or for your own company. Bash can reply right away, act in apps, call your tools, or start a task (a longer piece of work) on its own computer. You can follow every step as it happens.
Ask for one of your users
Name them with your own id. Their Bash is created the first time you do.
import { Vestra } from '@vestra/sdk';const vestra = new Vestra(); // reads VESTRA_API_KEY and VESTRA_BASE_URL const traveller = vestra.user('traveller-42'); const run = traveller.ask('My 6am flight got cancelled. What should I do?');for await (const event of run) { if (event.type === 'task.started') console.log(`Working on: ${event.data.title ?? 'a task'}`);}console.log(await run.text());Ask a follow-up
It goes to the same conversation.
console.log(await run.ask('Can I get a refund for it?').text());Stop a reply and its work
This stops the reply and every task the conversation started.
const hotel = traveller.ask('Find me a hotel near the airport.');await hotel.stop();Ask for your company
Leave the user out, and the job goes to your company's own Bash.
console.log(await vestra.ask('Write a two-line notice for our travellers about storm delays at Mumbai airport today.').text());Ask for many users at once
Each user gets their own conversation. If Bash asks one of them a question, that item waits for the answer, and so does wait().
const affected = [ { id: 'traveller-42', city: 'Mumbai' }, { id: 'traveller-77', city: 'Pune' },];const batch = vestra.ask(affected.map((t) => ({ user: t.id, message: `A storm may delay flights from ${t.city} today. What should I do before I leave for the airport? Two lines, in general: no need to look up my booking.` })));console.log((await batch.wait()).counts);Ask for one of your users
Name them with your own id. Their Bash is created the first time you do.
from vestra import Vestravestra = Vestra() # reads VESTRA_API_KEY and VESTRA_BASE_URL traveller = vestra.user("traveller-42") run = traveller.ask("My 6am flight got cancelled. What should I do?")for event in run: if event.type == "task.started": print(f"Working on: {event.data.get('title') or 'a task'}")print(run.text())Ask a follow-up
It goes to the same conversation.
print(run.ask("Can I get a refund for it?").text())Stop a reply and its work
This stops the reply and every task the conversation started.
hotel = traveller.ask("Find me a hotel near the airport.")hotel.stop()Ask for your company
Leave the user out, and the job goes to your company's own Bash.
print(vestra.ask("Write a two-line notice for our travellers about storm delays at Mumbai airport today.").text())Ask for many users at once
Each user gets their own conversation. If Bash asks one of them a question, that item waits for the answer, and so does wait().
affected = [{"id": "traveller-42", "city": "Mumbai"}, {"id": "traveller-77", "city": "Pune"}]batch = vestra.ask([{"user": t["id"], "message": f"A storm may delay flights from {t['city']} today. What should I do before I leave for the airport? Two lines, in general: no need to look up my booking."} for t in affected])print(batch.wait().counts)Ask for one of your users
Approvals and questions appear right here in the terminal. Ctrl-C stops it.
vestra ask "My 6am flight got cancelled. What should I do?" --user traveller-42Ask a follow-up
It goes to the same conversation.
vestra ask "Can I get a refund for it?" --user traveller-42 --conversation conv_8f2kStop a reply and its work
This stops the reply and every task the conversation started.
vestra ask --stop conv_8f2kAsk for your company
Leave the user out, and the job goes to your company's own Bash.
vestra ask "Write a two-line notice for our travellers about storm delays at Mumbai airport today."Ask for many users at once
Pass a CSV with one user id per line, and each user gets their own conversation. If Bash asks one of them a question, that item waits for the answer.
vestra ask "A storm may delay flights from Mumbai today. What should I do before I leave for the airport? Two lines, in general: no need to look up my booking." --users travellers.csvAsk for one of your users
Their Bash is created the first time you name them. With stream: true, the response streams this turn's events as they happen, and ends when the turn is over.
curl -N "$VESTRA_BASE_URL/v1/conversations" \ -H "Authorization: Bearer $VESTRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "user_id": "traveller-42", "message": "My 6am flight got cancelled. What should I do?", "stream": true }'Ask a follow-up
It goes to the same conversation.
curl -N "$VESTRA_BASE_URL/v1/conversations/conv_8f2k/messages" \ -H "Authorization: Bearer $VESTRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "message": "Can I get a refund for it?", "stream": true }'Stop a reply and its work
This stops the reply and every task the conversation started.
curl -X POST "$VESTRA_BASE_URL/v1/conversations/conv_8f2k/stop" \ -H "Authorization: Bearer $VESTRA_API_KEY"Ask for your company
Leave user_id out, and the job goes to your company's own Bash.
curl "$VESTRA_BASE_URL/v1/conversations" \ -H "Authorization: Bearer $VESTRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "message": "Write a two-line notice for our travellers about storm delays at Mumbai airport today." }'Ask for many users at once
Each user gets their own conversation. If Bash asks one of them a question, that item waits for the answer.
curl "$VESTRA_BASE_URL/v1/batches" \ -H "Authorization: Bearer $VESTRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "items": [ { "user_id": "traveller-42", "message": "A storm may delay flights from Mumbai today. What should I do before I leave for the airport? Two lines, in general: no need to look up my booking." }, { "user_id": "traveller-77", "message": "A storm may delay flights from Pune today. What should I do before I leave for the airport? Two lines, in general: no need to look up my booking." } ] }'{ "method": "tools/call", "params": { "name": "ask", "arguments": { "user": "traveller-42", "message": "My 6am flight got cancelled. Get me on the next one." } }}Good to know
Who the job is for
vestra.user(id) acts for one of your users, named by your own id. The id is 1 to 128 characters and starts with a letter or digit. The user is created the first time you name them. Leave the user out, and the job goes to your company's own Bash, the one that works for your company rather than for a user. Over HTTP, the field is user_id.
When the reply has no text
A turn is your message and Bash's reply to it. When Bash only starts a task and says nothing, the turn can end with an empty message.completed.text. The task's name is in the task.started event, in its data.title, and its result arrives with task.completed.
When a job is stopped or fails
When a job is stopped or fails, the turn ends first, before the events that end its tasks arrive. A stream: true call closes when the turn ends. Then task.stopped or task.failed follow on the conversation's stream, on GET /v1/events and on your webhooks.
Conversation status
A conversation is idle when nothing is happening, replying while Bash writes its reply, working while tasks it started are running, and waiting while Bash waits for you: an approval, an answer, a hand-off (a step only a person can do) or one of your tools. Each change arrives as a conversation.status event, with the turn's turn_id and turn_status.
Asking many users at once
Pass a list of { user, message } to ask many users at once. This is a batch (POST /v1/batches), and each item gets its own conversation. Items with no user run on your company's own Bash, at most 5 at a time.
What a job cost
run.cost() returns the conversation's billed cost once the run ends. cost_complete stays false while charges from the tasks it started can still arrive. For the itemized receipt, read the line items on usage.
The routes behind ask14 routes, each with every field in the API reference
runtime (or all)runtime (or all)runtime (or all)runtime (or all)runtime (or all)runtime (or all)runtime (or all)runtime (or all)runtime (or all)runtime (or all)