> ## Documentation Index
> Fetch the complete documentation index at: https://docs.praison.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Submit Run API

> Submit a new async job for execution

Submit a new long-running agent task for asynchronous execution.

<ParamField header="Idempotency-Key" type="string">
  Unique key to prevent duplicate job submissions. If a job with this key already exists, the existing job is returned.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`
</ParamField>

<ParamField body="prompt" type="string" required>
  The task prompt or instruction for the agent to execute.
</ParamField>

<ParamField body="agent_file" type="string">
  Path to the agent configuration YAML file. Defaults to `agents.yaml`.
</ParamField>

<ParamField body="framework" type="string">
  Framework to use for execution. Defaults to `praisonai`.
</ParamField>

<ParamField body="timeout" type="integer">
  Maximum execution time in seconds. Defaults to `3600` (1 hour).
</ParamField>

<ParamField body="webhook_url" type="string">
  URL to receive a callback when the job completes. The callback includes the job result.
</ParamField>

<ParamField body="session_id" type="string">
  Group related jobs together with a session identifier.
</ParamField>

## Response

<ResponseField name="job_id" type="string" required>
  Unique identifier for the submitted job (e.g., `run_abc123`).
</ResponseField>

<ResponseField name="status" type="string" required>
  Initial job status, typically `queued`.
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 timestamp of job creation.
</ResponseField>

<ResponseField name="poll_url" type="string" required>
  URL to poll for job status updates.
</ResponseField>

<ResponseField name="stream_url" type="string" required>
  URL for SSE streaming of job progress.
</ResponseField>

## Response Headers

| Header        | Description                           |
| ------------- | ------------------------------------- |
| `Location`    | URL to poll for job status            |
| `Retry-After` | Recommended seconds before first poll |

<RequestExample>
  ```bash cURL theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  curl -X POST http://127.0.0.1:8005/api/v1/runs \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: unique-key-123" \
    -d '{
      "prompt": "Analyze the quarterly sales data",
      "timeout": 3600,
      "webhook_url": "https://example.com/callback",
      "session_id": "project-alpha"
    }'
  ```

  ```python Python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  import httpx

  response = httpx.post(
      "http://127.0.0.1:8005/api/v1/runs",
      json={
          "prompt": "Analyze the quarterly sales data",
          "timeout": 3600,
          "webhook_url": "https://example.com/callback",
          "session_id": "project-alpha"
      },
      headers={"Idempotency-Key": "unique-key-123"}
  )

  job = response.json()
  print(f"Job ID: {job['job_id']}")
  print(f"Poll URL: {job['poll_url']}")
  ```

  ```bash CLI theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  praisonai run submit "Analyze the quarterly sales data" \
    --idempotency-key unique-key-123 \
    --timeout 3600 \
    --webhook-url https://example.com/callback \
    --session-id project-alpha
  ```
</RequestExample>

<ResponseExample>
  ```json 202 Accepted theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  {
    "job_id": "run_abc123",
    "status": "queued",
    "created_at": "2025-01-01T00:00:00Z",
    "poll_url": "http://127.0.0.1:8005/api/v1/runs/run_abc123",
    "stream_url": "http://127.0.0.1:8005/api/v1/runs/run_abc123/stream"
  }
  ```

  ```json 409 Conflict (Duplicate Idempotency Key) theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  {
    "job_id": "run_abc123",
    "status": "running",
    "message": "Job already exists with this idempotency key"
  }
  ```
</ResponseExample>

## Idempotency

Use the `Idempotency-Key` header to ensure a job is only created once, even if the request is retried:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import httpx

# Safe to retry - same key returns existing job
for attempt in range(3):
    try:
        response = httpx.post(
            "http://127.0.0.1:8005/api/v1/runs",
            json={"prompt": "Process data"},
            headers={"Idempotency-Key": "unique-operation-id"},
            timeout=10
        )
        break
    except httpx.TimeoutException:
        continue
```

## Webhook Callback

When `webhook_url` is provided, the server sends a POST request to that URL when the job completes:

```json theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
{
  "job_id": "run_abc123",
  "status": "succeeded",
  "result": "Task output here",
  "duration_seconds": 45.2
}
```

## Error Responses

| Status | Description                             |
| ------ | --------------------------------------- |
| `400`  | Bad request - missing or invalid prompt |
| `409`  | Conflict - duplicate idempotency key    |
| `422`  | Validation error - invalid request body |
| `500`  | Internal server error                   |

## See Also

* [Get Run Status](/docs/api/praisonai/async-jobs/get-run-status)
* [Stream Run](/docs/api/praisonai/async-jobs/stream-run)
* [Async Jobs Overview](/docs/api/praisonai/async-jobs)
