Run Execution
curl --request POST \
--url https://api.velt.dev/v2/agents/execution/run \
--header 'Content-Type: application/json' \
--header 'x-velt-api-key: <x-velt-api-key>' \
--header 'x-velt-auth-token: <x-velt-auth-token>' \
--data '
{
"data": {
"agentId": "<string>",
"url": "<string>",
"crossPageExecute": true,
"maxUrlsToProcess": 123,
"deviceType": "<string>",
"organizationId": "<string>",
"documentId": "<string>",
"annotationVisibility": "<string>",
"trigger": "<string>",
"workflowExecutionId": "<string>",
"ranBy": {},
"userContext": {},
"aiConfig": {}
}
}
'import requests
url = "https://api.velt.dev/v2/agents/execution/run"
payload = { "data": {
"agentId": "<string>",
"url": "<string>",
"crossPageExecute": True,
"maxUrlsToProcess": 123,
"deviceType": "<string>",
"organizationId": "<string>",
"documentId": "<string>",
"annotationVisibility": "<string>",
"trigger": "<string>",
"workflowExecutionId": "<string>",
"ranBy": {},
"userContext": {},
"aiConfig": {}
} }
headers = {
"x-velt-api-key": "<x-velt-api-key>",
"x-velt-auth-token": "<x-velt-auth-token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-velt-api-key': '<x-velt-api-key>',
'x-velt-auth-token': '<x-velt-auth-token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: {
agentId: '<string>',
url: '<string>',
crossPageExecute: true,
maxUrlsToProcess: 123,
deviceType: '<string>',
organizationId: '<string>',
documentId: '<string>',
annotationVisibility: '<string>',
trigger: '<string>',
workflowExecutionId: '<string>',
ranBy: {},
userContext: {},
aiConfig: {}
}
})
};
fetch('https://api.velt.dev/v2/agents/execution/run', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.velt.dev/v2/agents/execution/run",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'data' => [
'agentId' => '<string>',
'url' => '<string>',
'crossPageExecute' => true,
'maxUrlsToProcess' => 123,
'deviceType' => '<string>',
'organizationId' => '<string>',
'documentId' => '<string>',
'annotationVisibility' => '<string>',
'trigger' => '<string>',
'workflowExecutionId' => '<string>',
'ranBy' => [
],
'userContext' => [
],
'aiConfig' => [
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-velt-api-key: <x-velt-api-key>",
"x-velt-auth-token: <x-velt-auth-token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.velt.dev/v2/agents/execution/run"
payload := strings.NewReader("{\n \"data\": {\n \"agentId\": \"<string>\",\n \"url\": \"<string>\",\n \"crossPageExecute\": true,\n \"maxUrlsToProcess\": 123,\n \"deviceType\": \"<string>\",\n \"organizationId\": \"<string>\",\n \"documentId\": \"<string>\",\n \"annotationVisibility\": \"<string>\",\n \"trigger\": \"<string>\",\n \"workflowExecutionId\": \"<string>\",\n \"ranBy\": {},\n \"userContext\": {},\n \"aiConfig\": {}\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-velt-api-key", "<x-velt-api-key>")
req.Header.Add("x-velt-auth-token", "<x-velt-auth-token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.velt.dev/v2/agents/execution/run")
.header("x-velt-api-key", "<x-velt-api-key>")
.header("x-velt-auth-token", "<x-velt-auth-token>")
.header("Content-Type", "application/json")
.body("{\n \"data\": {\n \"agentId\": \"<string>\",\n \"url\": \"<string>\",\n \"crossPageExecute\": true,\n \"maxUrlsToProcess\": 123,\n \"deviceType\": \"<string>\",\n \"organizationId\": \"<string>\",\n \"documentId\": \"<string>\",\n \"annotationVisibility\": \"<string>\",\n \"trigger\": \"<string>\",\n \"workflowExecutionId\": \"<string>\",\n \"ranBy\": {},\n \"userContext\": {},\n \"aiConfig\": {}\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.velt.dev/v2/agents/execution/run")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-velt-api-key"] = '<x-velt-api-key>'
request["x-velt-auth-token"] = '<x-velt-auth-token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"data\": {\n \"agentId\": \"<string>\",\n \"url\": \"<string>\",\n \"crossPageExecute\": true,\n \"maxUrlsToProcess\": 123,\n \"deviceType\": \"<string>\",\n \"organizationId\": \"<string>\",\n \"documentId\": \"<string>\",\n \"annotationVisibility\": \"<string>\",\n \"trigger\": \"<string>\",\n \"workflowExecutionId\": \"<string>\",\n \"ranBy\": {},\n \"userContext\": {},\n \"aiConfig\": {}\n }\n}"
response = http.request(request)
puts response.read_body{
"result": {
"status": "success",
"message": "Agent execution created successfully",
"data": {
"executionId": "exec_1711900000000_abc123def456"
}
}
}
Execution
Run Execution
POST
/
v2
/
agents
/
execution
/
run
Run Execution
curl --request POST \
--url https://api.velt.dev/v2/agents/execution/run \
--header 'Content-Type: application/json' \
--header 'x-velt-api-key: <x-velt-api-key>' \
--header 'x-velt-auth-token: <x-velt-auth-token>' \
--data '
{
"data": {
"agentId": "<string>",
"url": "<string>",
"crossPageExecute": true,
"maxUrlsToProcess": 123,
"deviceType": "<string>",
"organizationId": "<string>",
"documentId": "<string>",
"annotationVisibility": "<string>",
"trigger": "<string>",
"workflowExecutionId": "<string>",
"ranBy": {},
"userContext": {},
"aiConfig": {}
}
}
'import requests
url = "https://api.velt.dev/v2/agents/execution/run"
payload = { "data": {
"agentId": "<string>",
"url": "<string>",
"crossPageExecute": True,
"maxUrlsToProcess": 123,
"deviceType": "<string>",
"organizationId": "<string>",
"documentId": "<string>",
"annotationVisibility": "<string>",
"trigger": "<string>",
"workflowExecutionId": "<string>",
"ranBy": {},
"userContext": {},
"aiConfig": {}
} }
headers = {
"x-velt-api-key": "<x-velt-api-key>",
"x-velt-auth-token": "<x-velt-auth-token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-velt-api-key': '<x-velt-api-key>',
'x-velt-auth-token': '<x-velt-auth-token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: {
agentId: '<string>',
url: '<string>',
crossPageExecute: true,
maxUrlsToProcess: 123,
deviceType: '<string>',
organizationId: '<string>',
documentId: '<string>',
annotationVisibility: '<string>',
trigger: '<string>',
workflowExecutionId: '<string>',
ranBy: {},
userContext: {},
aiConfig: {}
}
})
};
fetch('https://api.velt.dev/v2/agents/execution/run', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.velt.dev/v2/agents/execution/run",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'data' => [
'agentId' => '<string>',
'url' => '<string>',
'crossPageExecute' => true,
'maxUrlsToProcess' => 123,
'deviceType' => '<string>',
'organizationId' => '<string>',
'documentId' => '<string>',
'annotationVisibility' => '<string>',
'trigger' => '<string>',
'workflowExecutionId' => '<string>',
'ranBy' => [
],
'userContext' => [
],
'aiConfig' => [
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-velt-api-key: <x-velt-api-key>",
"x-velt-auth-token: <x-velt-auth-token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.velt.dev/v2/agents/execution/run"
payload := strings.NewReader("{\n \"data\": {\n \"agentId\": \"<string>\",\n \"url\": \"<string>\",\n \"crossPageExecute\": true,\n \"maxUrlsToProcess\": 123,\n \"deviceType\": \"<string>\",\n \"organizationId\": \"<string>\",\n \"documentId\": \"<string>\",\n \"annotationVisibility\": \"<string>\",\n \"trigger\": \"<string>\",\n \"workflowExecutionId\": \"<string>\",\n \"ranBy\": {},\n \"userContext\": {},\n \"aiConfig\": {}\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-velt-api-key", "<x-velt-api-key>")
req.Header.Add("x-velt-auth-token", "<x-velt-auth-token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.velt.dev/v2/agents/execution/run")
.header("x-velt-api-key", "<x-velt-api-key>")
.header("x-velt-auth-token", "<x-velt-auth-token>")
.header("Content-Type", "application/json")
.body("{\n \"data\": {\n \"agentId\": \"<string>\",\n \"url\": \"<string>\",\n \"crossPageExecute\": true,\n \"maxUrlsToProcess\": 123,\n \"deviceType\": \"<string>\",\n \"organizationId\": \"<string>\",\n \"documentId\": \"<string>\",\n \"annotationVisibility\": \"<string>\",\n \"trigger\": \"<string>\",\n \"workflowExecutionId\": \"<string>\",\n \"ranBy\": {},\n \"userContext\": {},\n \"aiConfig\": {}\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.velt.dev/v2/agents/execution/run")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-velt-api-key"] = '<x-velt-api-key>'
request["x-velt-auth-token"] = '<x-velt-auth-token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"data\": {\n \"agentId\": \"<string>\",\n \"url\": \"<string>\",\n \"crossPageExecute\": true,\n \"maxUrlsToProcess\": 123,\n \"deviceType\": \"<string>\",\n \"organizationId\": \"<string>\",\n \"documentId\": \"<string>\",\n \"annotationVisibility\": \"<string>\",\n \"trigger\": \"<string>\",\n \"workflowExecutionId\": \"<string>\",\n \"ranBy\": {},\n \"userContext\": {},\n \"aiConfig\": {}\n }\n}"
response = http.request(request)
puts response.read_body{
"result": {
"status": "success",
"message": "Agent execution created successfully",
"data": {
"executionId": "exec_1711900000000_abc123def456"
}
}
}
Use this API to start an asynchronous agent execution. The engine creates an execution document in Firestore and dispatches a Cloud Task for processing. The response returns immediately with the
Errors:
executionId. Poll Get Execution to track progress and fetch findings.
The apiKey is injected from request headers. organizationId and documentId are required and identify the document the execution runs against: the document must already exist, and findings are persisted to it as comment annotations. Cross-page execution is controlled via the crossPageExecute boolean; there is no separate endpoint.
The schema uses .passthrough() so any additional fields are forwarded.
Endpoint
POST https://api.velt.dev/v2/agents/execution/run
Headers
string
required
Your API key.
string
required
Your Auth Token.
Body
Params
object
required
Show properties
Show properties
string
required
Min 1 char. Agent ID to execute.
string
required
Valid URL. The seed URL to process.
boolean
When true, the engine crawls the seed URL and processes up to
maxUrlsToProcess pages. Default: false.number
Max URLs to process when
crossPageExecute: true. Positive integer. Default: 50.string
Device mode to emulate for this execution:
"mobile" or "desktop". Default: "desktop". Drives the Puppeteer viewport/user-agent used by all context-gathering strategies and pin resolution, and sets pageInfo.deviceInfo.deviceType on every annotation the execution creates.string
required
Organization ID. Identifies the organization the execution runs against; findings are persisted to it as comment annotations.
string
required
Document ID. The document must already exist (unknown documents return
NOT_FOUND); findings are persisted to it as comment annotations.string
Sets who can see the comment annotations this execution creates:
"public" or "private". Default: "private".With "private", each annotation is created with visibility { type: "organizationPrivate", organizationId }. Only members and admins of the execution’s organization see the finding pins.With "public", each annotation is created with visibility { type: "public" }. Anyone with access to the document sees the finding pins, including users outside the organization.These two are the only accepted values; request validation rejects any other string. Omitting the field resolves to "private". The execution never overrides an annotation that already carries its own visibility.string
"standalone" (default) or "workflow". Use "workflow" when running an agent as part of a Review Workflow Builder workflow node.string
Parent workflow execution ID. Pair with
trigger: "workflow".object
User who triggered the execution.
| Field | Type | Required | Description |
|---|---|---|---|
userId | string | yes (if ranBy) | User ID |
name | string | no | Display name. Default: "". |
email | string | no | Email. Default: "". |
object
Runtime values for the agent’s
userContextFields. Keys must match the field IDs declared in the agent’s input.userContextFields.object
Per-execution LLM override. Omit it to run on the provider and model the platform resolves for the agent.
Validation rules specific to this object:
| Field | Type | Required | Description |
|---|---|---|---|
provider | string | no | "gemini", "claude", or "openai". Any other value is rejected. |
model | string | no | Pins one model for this run. Must be on the allowlist (see below). Pair it with provider. |
defaultModels | object | no | Per-provider model policy, { "<provider>": "<model>" }. Each key must be a valid provider and each value must be on that provider’s allowlist. |
maxToolTurns | number | no | Tool-loop turn budget for the mcp-tools execution strategy. Integer 1..16. |
model and defaultModels solve different problems. model pins a single model for this run, which is only correct when you know the agent’s provider. defaultModels is the per-provider form: send it when you reuse one aiConfig across many runs whose agents sit on different providers, so each run picks up the right model for whichever provider its agent resolves to. Sending both is allowed.Allowed models. A request cannot point an execution at an arbitrary model string.
Sending
model is validated against the allowlist for the supplied provider, or against the union of every provider’s allowlist when provider is omitted. The allowlist is deliberately narrow, currently one model per provider:| Provider | Allowed model |
|---|---|
gemini | gemini-3.6-flash |
claude | claude-sonnet-5 |
openai | gpt-5.6-luna |
model without provider only passes a weaker check. The model is re-checked at execution time against the provider the agent actually resolves to, and if it does not match, the override is dropped and the run falls back to that provider’s default model. The request still returns 200 and nothing in the response tells you the pin was ignored. Send provider alongside model, or use defaultModels, to guarantee the pin.- Unlike the rest of the request body,
aiConfigrejects unknown keys. A typo such asmodellreturnsINVALID_ARGUMENTinstead of being silently ignored. - At least one of
provider,model,defaultModels, ormaxToolTurnsmust be present. An emptyaiConfig: {}is rejected. defaultModelscannot be an empty object.
Example Requests
1. Single page execution
{
"data": {
"agentId": "abc123def456",
"url": "https://example.com/pricing",
"organizationId": "org_001",
"documentId": "doc_001",
"deviceType": "desktop",
"ranBy": {
"userId": "user_123",
"name": "Jane Doe",
"email": "jane@example.com"
}
}
}
2. Cross-page execution with user context (mobile)
{
"data": {
"agentId": "abc123def456",
"url": "https://example.com",
"crossPageExecute": true,
"maxUrlsToProcess": 25,
"deviceType": "mobile",
"organizationId": "org_001",
"documentId": "doc_001",
"trigger": "standalone",
"userContext": {
"brand_color": "#1A73E8",
"brand_font": "Inter",
"check_images": true
},
"ranBy": {
"userId": "user_123",
"name": "Jane Doe",
"email": "jane@example.com"
}
}
}
3. Workflow-triggered execution
{
"data": {
"agentId": "abc123def456",
"url": "https://example.com",
"trigger": "workflow",
"workflowExecutionId": "wf_exec_789",
"organizationId": "org_001",
"documentId": "doc_001",
"ranBy": { "userId": "user_123" }
}
}
4. Execution with public annotations
{
"data": {
"agentId": "abc123def456",
"url": "https://example.com/pricing",
"organizationId": "org_001",
"documentId": "doc_001",
"annotationVisibility": "public",
"ranBy": { "userId": "user_123" }
}
}
5. Pinning a provider and model for one run
{
"data": {
"agentId": "abc123def456",
"url": "https://example.com/pricing",
"organizationId": "org_001",
"documentId": "doc_001",
"aiConfig": {
"provider": "claude",
"model": "claude-sonnet-5"
}
}
}
6. Per-provider model policy across mixed agents
{
"data": {
"agentId": "abc123def456",
"url": "https://example.com",
"organizationId": "org_001",
"documentId": "doc_001",
"aiConfig": {
"defaultModels": {
"gemini": "gemini-3.6-flash",
"claude": "claude-sonnet-5"
},
"maxToolTurns": 12
}
}
}
7. Minimal request
{
"data": {
"agentId": "abc123def456",
"url": "https://example.com",
"organizationId": "org_001",
"documentId": "doc_001"
}
}
Response
Success Response
{
"result": {
"status": "success",
"message": "Agent execution created successfully",
"data": {
"executionId": "exec_1711900000000_abc123def456"
}
}
}
| Field | Type | Description |
|---|---|---|
data.executionId | string | Unique execution ID. Use to poll via Get Execution. |
Failure Response
{
"error": {
"message": "ERROR_MESSAGE",
"status": "INVALID_ARGUMENT"
}
}
INVALID_ARGUMENT: invalid URL; missingagentId,organizationId, ordocumentId; or an invalidtrigger,deviceType, orannotationVisibility.INVALID_ARGUMENT: anaiConfigthat is empty, carries an unknown key, names a provider outsidegemini/claude/openai, names a model outside the allowlist, supplies an emptydefaultModels, or setsmaxToolTurnsoutside1..16.NOT_FOUND: store database not found, or the target document does not exist.ALREADY_EXISTS: an execution is already running for this agent and document combination. The error message includes the running execution’s ID.RESOURCE_EXHAUSTED: the workspace’s AI credits are exhausted.
{
"result": {
"status": "success",
"message": "Agent execution created successfully",
"data": {
"executionId": "exec_1711900000000_abc123def456"
}
}
}
Was this page helpful?
⌘I

