# ask

> Send a job in plain words, for one user, many users or your company.

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.

## TypeScript

```ts
import { Vestra } from '@vestra/sdk';
const vestra = new Vestra(); // reads VESTRA_API_KEY and VESTRA_BASE_URL

// Ask for one of your users. Name them with your own id. Their Bash is created the first time you do.
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);
```

## Python

```python
from vestra import Vestra
vestra = Vestra()  # reads VESTRA_API_KEY and VESTRA_BASE_URL

# Ask for one of your users. Name them with your own id. Their Bash is created the first time you do.
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)
```

## CLI

```bash
# 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-42

# Ask a follow-up. It goes to the same conversation.
vestra ask "Can I get a refund for it?" --user traveller-42 --conversation conv_8f2k

# Stop a reply and its work. This stops the reply and every task the conversation started.
vestra ask --stop conv_8f2k

# Ask 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.csv
```

## HTTP

```bash
# 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

```json
{
  "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`](https://vestra.ai/developers/usage.md).

## The routes behind ask

- `POST` [/v1/conversations](https://vestra.ai/developers/reference/api/conversations/post-v1-conversations.md): Ask. 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. Key scope: `runtime` (or `all`).
- `GET` [/v1/conversations](https://vestra.ai/developers/reference/api/conversations/get-v1-conversations.md): Conversations, 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). Key scope: `runtime` (or `all`).
- `GET` [/v1/conversations/{conversation_id}](https://vestra.ai/developers/reference/api/conversations/get-v1-conversations-conversation-id.md): One conversation: status (idle, replying, working, waiting), its open work, its open approvals. Key scope: `runtime` (or `all`).
- `POST` [/v1/conversations/{conversation_id}/messages](https://vestra.ai/developers/reference/api/conversations/post-v1-conversations-conversation-id-messages.md): Send 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. Key scope: `runtime` (or `all`).
- `GET` [/v1/conversations/{conversation_id}/messages](https://vestra.ai/developers/reference/api/conversations/get-v1-conversations-conversation-id-messages.md): The conversation, paged: your messages, Bash's replies, and summaries of the work it did. Key scope: `runtime` (or `all`).
- `POST` [/v1/conversations/{conversation_id}/stop](https://vestra.ai/developers/reference/api/conversations/post-v1-conversations-conversation-id-stop.md): Stop the reply and every piece of work the conversation started. Key scope: `runtime` (or `all`).
- `GET` [/v1/tasks](https://vestra.ai/developers/reference/api/work/get-v1-tasks.md): All work across your users, or one user's with user_id. Filter by status, deployment, conversation or date too. Key scope: `runtime` (or `all`).
- `GET` [/v1/tasks/{task_id}](https://vestra.ai/developers/reference/api/work/get-v1-tasks-task-id.md): Status, title, the progress list, the result (text, and data when an output_schema was set), the outcome, cost so far. Key scope: `runtime` (or `all`).
- `DELETE` [/v1/tasks/{task_id}](https://vestra.ai/developers/reference/api/work/delete-v1-tasks-task-id.md): Delete it and its outputs. Key scope: `runtime` (or `all`).
- `POST` [/v1/tasks/{task_id}/stop](https://vestra.ai/developers/reference/api/work/post-v1-tasks-task-id-stop.md): Stop this piece of work only. Key scope: `runtime` (or `all`).
- `POST` [/v1/batches](https://vestra.ai/developers/reference/api/batches/post-v1-batches.md): Start a batch: a deployment, a list of items (user_id optional, message, context, metadata) and a concurrency. Each item is one conversation message with hand_off: always. Key scope: `runtime` (or `all`).
- `GET` [/v1/batches/{batch_id}](https://vestra.ai/developers/reference/api/batches/get-v1-batches-batch-id.md): Progress: counts by status, spend so far. Key scope: `runtime` (or `all`).
- `GET` [/v1/batches/{batch_id}/items](https://vestra.ai/developers/reference/api/batches/get-v1-batches-batch-id-items.md): Each item with its task id and result. Key scope: `runtime` (or `all`).
- `POST` [/v1/batches/{batch_id}/cancel](https://vestra.ai/developers/reference/api/batches/post-v1-batches-batch-id-cancel.md): Stop starting new items; running ones finish. Key scope: `runtime` (or `all`).

Next: [`routines`](https://vestra.ai/developers/routines.md)
