Conversations
Ask Bash in a conversation, follow its reply as it happens, and stop it.
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.
Request12 fields
Path
conversation_idstringrequiredThe conversation's id (conv_...).
- Type
string
Headers
Idempotency-KeystringSend the same key to retry this call safely for 24 hours.
- Type
string
Preferstringwait=N (N at most 120) holds the call until the turn and its work finish.
- Type
string
Body
messagestringWhat you or your user say to Bash, in at most 32,000 characters. Default: empty, for a send that carries only attachments.
- Default
- Empty.
- Limits
- At most 32000 characters.
- Example
My 6am flight got cancelled. Book me on the next one.
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"How a message reaches Bash. auto: Bash reads it, replies, and starts work when the job needs it. always: it goes straight to work, as a task; the reply is the one line Started work on it.
- Default
auto
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"}
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 200 or 20213 fields
idstringThe turn: one message and all it led to (turn_...).
- Type
string
object"conversation.turn"Always conversation.turn.
- Type
"conversation.turn"
conversation_idstringIts conversation (conv_...).
- Type
string
status"running" | "working" | "requires_action" | "completed" | "failed" | "stopped"Where one message is. running: Bash is replying. working: the work it started is open. requires_action: it waits on a call to one of your tools. completed, failed or stopped: it has settled.
- Type
"running" | "working" | "requires_action" | "completed" | "failed" | "stopped"
replystring | nullBash's reply; null until it is written. For a message sent straight to work it is the one line Started work on it.
- Type
string | null
answerstring | nullThe reply's answer: its final words, the part after any search or lookup Bash made on the way, trimmed; null until the reply is written, or when it said nothing. A turn from before this field holds its whole reply. When Bash went to work, the work's own answer is GET /v1/tasks/{id}'s result.text.
- Type
string | null
dataany | nullThe data you asked for with output_schema, matching it; null when you asked for none.
- Type
any | null
outcomeobject | nullYour success_criteria, judged once the turn and its work settle; null when you gave none.
metbooleanWhether the result meets your success_criteria.
- Type
boolean
reasonstringWhy, in a sentence.
- Type
string
workobject[]The work this turn started.
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"
resultstring | nullIts answer, its final reply, cut to 280 characters; null until it has any. The whole answer is GET /v1/tasks/{id}'s result.text.
- Type
string | null
tool_callsobject[]While it requires action: the calls to your tools it waits on. Empty otherwise.
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
errorobject | nullWhy the turn failed; null unless it did.
codestringWhy it failed, as a code: output_invalid (the answer did not match output_schema), work_lost (your answer never reached the work), process_lost (our side was cut off mid-reply; send it again), or Bash's own: credits_exhausted, model_timeout, tool_failed, bad_tool_args, loop_exhausted, unauthorized or internal.
- Type
string
messagestringWhat went wrong, in plain words.
- Type
string
created_atstringWhen the message was sent, as an ISO 8601 time.
- Type
string
finished_atstring | nullWhen the turn settled, as an ISO 8601 time; null while it runs.
- Type
string | null
const reply = await vestra.user('traveller-42').ask('Make it a window seat.', { conversation: 'conv_8f2k' }).text();reply = vestra.user("traveller-42").ask("Make it a window seat.", conversation="conv_8f2k").text()vestra ask "Make it a window seat." --user traveller-42 --conversation conv_8f2k# 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." } }}