BashBrainTeammatesPricingDevelopersGet a test key

Conversations

Ask Bash in a conversation, follow its reply as it happens, and stop it.

Send Authorization: Bearer vk_test_... on every call. Every route of Conversations.

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.

Your API key, or a session's token, scope runtime or all. On the card: ask. Every call here is a checked sample.

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
TypeScript
const reply = await vestra.user('traveller-42').ask('Make it a window seat.', { conversation: 'conv_8f2k' }).text();
Python
reply = vestra.user("traveller-42").ask("Make it a window seat.", conversation="conv_8f2k").text()
CLI
vestra ask "Make it a window seat." --user traveller-42 --conversation conv_8f2k
HTTP
# 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." }    ]  }'
MCP
{  "method": "tools/call",  "params": {    "name": "ask",    "arguments": {      "user": "traveller-42",      "message": "My 6am flight got cancelled. Get me on the next one."    }  }}