Conversations
Ask Bash in a conversation, follow its reply as it happens, and stop it.
RoutesOpen one for every field it takes and answers.
POST/v1/conversationsAsk.
Start a conversation, optionally with its first message and that message's options (context, attachments, output_schema, success_criteria, tools, hand_off). user_id names whose Bash it is, created on first use; leave it out for the company's own Bash. stream: true answers the first turn's events as text/event-stream and ends when the turn settles.
Request12 fields
Headers
Idempotency-KeystringSend the same key to retry this call safely for 24 hours.
- Type
string
Body, if you send one
user_idstringYour id for the user this conversation is for; Vestra makes the user the first time you name them. Absent: your company's own Bash.
- Example
traveller-42
deploymentstringWhich deployment answers: its id (dep_...) or its name. Absent: the user's default deployment, then your company's.
- Limits
- At least 1 character.
- Example
travel-help
metadatamap of stringYour own labels, given back as you sent them: at most 32 keys of 1 to 64 characters, each value a string of at most 512. Bash never reads them.
- Example
{"order_id":"ORD-1042","channel":"app"}
messagestringA first message, in at most 32,000 characters. Absent, with no attachment: the conversation starts empty.
- Limits
- At most 32000 characters.
- Example
When does my flight on TN-48213 leave?
contextmap of anyFacts for this message only, as JSON. Bash reads them as data, never as instructions.
- Example
{"booking_reference":"TN-48213","tier":"gold"}
attachmentsobject[]Files Bash should read with this message: at most 10.
- Limits
- At most 10 items.
file_idstringrequiredA file you uploaded with POST /v1/files (file_...).
- Limits
- At least 1 character.
output_schemamap of anyA JSON Schema, at most 32 KB, for the data you want back: the turn's data matches it.
- Example
{"type":"object","properties":{"flight":{"type":"string"}},"required":["flight"]}
success_criteriastringWhat a good result looks like, in your words: when the turn settles, its outcome says whether it was met, and why.
- Limits
- 1 to 4000 characters.
- Example
A new booking on a flight that leaves before noon.
toolsobject[]Tools your code answers, for this message only, on top of the deployment's: at most 32.
- Limits
- At most 32 items.
namestringrequiredThe tool's name: lowercase letters, digits and underscores, starting with a letter, up to 64.
- Example
get_booking
descriptionstringrequiredWhat the tool does, so Bash knows when to call it, up to 1024 characters.
- Limits
- 1 to 1024 characters.
- Example
A booking by its PNR
input_schemamap of anyrequiredIts arguments, as JSON Schema with type: object. Bash's call fills them in.
- Example
{"type":"object","properties":{"pnr":{"type":"string"}},"required":["pnr"]}
timeout_sintegerSeconds Bash waits for your answer, 5 to 600. Default 120; after it, the call expires.
- Default
120- Limits
- 5 to 600.
read_onlybooleantrue: the tool changes nothing (a lookup), so Bash calls it without waiting for the person's yes. Absent: false.
- Type
boolean
run_without_askingbooleantrue: the tool changes something that needs no yes, so Bash calls it without waiting for the person's yes. Absent: false.
- Type
boolean
hand_off"auto" | "always"For the first message: auto lets Bash reply first; always sends it straight to work. Default: auto.
- Type
"auto" | "always"
streambooleantrue answers with the turn's events as they happen (text/event-stream), ending when the turn settles. Default: one JSON answer.
- Type
boolean
Answers 20116 fields
idstringThe conversation (conv_...).
- Example
conv_8f2k
object"conversation"Always conversation.
- Type
"conversation"
user_idstring | nullYour id for the user; null on your company's own Bash, and on an agent's conversation over A2A that names no user.
- Type
string | null
deployment_idstring | nullThe deployment that answers it (dep_...); null when it has none.
- Type
string | null
deployment_versioninteger | nullThe version of the deployment it runs on: in test mode the one it started on, in live mode the one live at its last message. Null with no deployment.
- Type
integer | null
status"idle" | "replying" | "working" | "waiting"What the conversation is doing. idle: nothing. replying: Bash is writing its reply. working: work Bash started is running. waiting: Bash waits on an approval, a question or a call to one of your tools.
- Type
"idle" | "replying" | "working" | "waiting"
metadatamap of stringYour labels, as you sent them; empty when you sent none.
- Type
map of string
created_atstringWhen it started, as an ISO 8601 time.
- Type
string
last_active_atstringWhen a message or its work last changed it, as an ISO 8601 time.
- Type
string
open_workobject[]Work Bash started that has not ended, oldest first.
task_idstringThe task (task_...).
- Type
string
titlestring | nullWhat the work is, in a few words; null until Bash names it.
- Type
string | null
status"queued" | "working" | "waiting" | "done" | "failed"Where a piece of work is. queued: not started yet. working: running on the user's computer. waiting: it waits on an approval or a question. done or failed: it has ended.
- Type
"queued" | "working" | "waiting" | "done" | "failed"
open_interactionsobject[]Approvals and questions Bash waits on.
interaction_idstringThe approval or question, to answer by its id (int_...).
- Type
string
task_idstringThe task that asked (task_...).
- Type
string
kindstringWhat it asks for, as stored: such as tool_permission, ask_question or composio_auth.
- Type
string
pending_tool_callsobject[]Calls to your tools that wait on your answer.
call_idstringThe call, to answer by its id (call_...).
- Type
string
namestringThe tool Bash called.
- Type
string
argumentsanyWhat Bash passed, matching the input schema of the tool.
- Type
any
task_idstring | nullThe task that made the call; null when Bash's reply made it.
- Type
string | null
last_event_seqintegerThe seq of the newest event on its stream: read the conversation, then follow its events after this seq, and you miss nothing.
- Type
integer
cost_usdnumberWhat it has cost so far, in billed US dollars: Bash's replies, all its work and its voice calls.
- Example
0.0412
cost_breakdownobjectThe same cost, by kind of spend.
orchestratornumberBash's own replies in the conversation, in billed US dollars; 0 on a piece of work.
- Type
number
intelligencenumberThe thinking Bash did while it worked, in billed US dollars.
- Type
number
toolsnumberThe tools and apps Bash used, in billed US dollars.
- Type
number
computenumberTime on Bash's computer, in billed US dollars.
- Type
number
backgroundnumberWork Bash did in the background, such as remembering and tidying, in billed US dollars.
- Type
number
voicenumberVoice call time, in billed US dollars.
- Type
number
turn_idstringmay be absentThe turn of the first message, when you sent one (turn_...).
- Type
string
const reply = await vestra.user('traveller-42').ask('My 6am flight got cancelled. Get me on the next one.').text();reply = vestra.user("traveller-42").ask("My 6am flight got cancelled. Get me on the next one.").text()vestra ask "My 6am flight got cancelled. Get me on the next one." --user traveller-42# Ask 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." } }}GET/v1/conversationsConversations, newest first: one user's with user_id, or every one of the company's without it (the company's own Bash shows user_id null).
GET/v1/conversations/{conversation_id}One conversation: status (idle, replying, working, waiting), its open work, its open approvals.
POST/v1/conversations/{conversation_id}/messagesSend a message.
Options: context (data for this turn only), attachments, output_schema, success_criteria, tools, hand_off (auto or always). Answers the turn at once; Prefer: wait=N holds for the final answer; stream: true answers this turn's events as text/event-stream and ends when the turn settles.
GET/v1/conversations/{conversation_id}/messagesThe conversation, paged: your messages, Bash's replies, and summaries of the work it did.
GET/v1/conversations/{conversation_id}/eventsThe one stream (SSE): replies as they are typed, work started and finished, progress, approvals, tool calls, files.
Resume with Last-Event-ID. Filter to one task's events with task_id.