Skip to content

Cloud Agents Quickstart

This walkthrough uses Bash, curl, and jq. First create a Runta API key and connect a model provider in the dashboard. See Model providers if no provider is available yet.

Terminal window
export RUNTA_API_URL="https://api.runta.com"
export RUNTA_TOKEN="rt..."
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $RUNTA_TOKEN" \
"$RUNTA_API_URL/v2/model-providers" |
jq '.model_providers[] | {id, display_name, protocol, default_model}'

Copy the id of the provider you want to use. This is a managed provider ID, not the provider’s API key or a model name.

Terminal window
export PROVIDER_ID="replace-with-a-provider-id-from-the-response"
Terminal window
AGENT=$(jq -n --arg provider "$PROVIDER_ID" '{
name: "My first Cloud Agent",
model_provider: {type: "managed", id: $provider},
runtime: {type: "fresh"},
system_prompt: "Be concise. Use your tools to verify your answers.",
initial_message: "Use bash to calculate 17 * 23, then report the result."
}' | curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $RUNTA_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @- "$RUNTA_API_URL/v2/agents") || exit 1
export AGENT_ID=$(printf '%s' "$AGENT" | jq -er '.id')
export RUNTIME_ID=$(printf '%s' "$AGENT" | jq -er '.runtime_id')
printf '%s\n' "$AGENT" | jq .

The response is 201 Created and contains id, runtime_id, harness_id, name, status, and creation/update timestamps. Save the returned IDs. Initialization continues after this response. The initial message starts after the runtime and platform setup are ready.

Run listing may be temporarily unavailable while the runtime boots. This bounded loop makes at most 60 attempts, sleeping five seconds between attempts, while stopping on authentication or other unexpected errors:

Terminal window
RUN_ID=""
for attempt in {1..60}; do
RESPONSE=$(curl --silent --show-error --max-time 10 \
-H "Authorization: Bearer $RUNTA_TOKEN" \
-w $'\n%{http_code}' \
"$RUNTA_API_URL/v2/agents/$AGENT_ID/runs?limit=1") || break
STATUS=${RESPONSE##*$'\n'}
BODY=${RESPONSE%$'\n'*}
case "$STATUS" in
200)
RUN_ID=$(printf '%s' "$BODY" | jq -r '.[0].id // empty')
if [ -n "$RUN_ID" ]; then break; fi
;;
409|503|504) ;;
*) printf 'Run lookup failed (%s): %s\n' "$STATUS" "$BODY" >&2; break ;;
esac
sleep 5
done
if [ -z "$RUN_ID" ]; then
printf 'No run is available yet. Inspect the agent and runtime before retrying.\n' >&2
exit 1
fi
export RUN_ID

If initialization fails, follow the troubleshooting guidance. Do not repeat agent creation just because the first run is still starting.

Terminal window
curl --fail-with-body --silent --show-error --no-buffer \
-H "Authorization: Bearer $RUNTA_TOKEN" \
-H "Accept: text/event-stream" \
"$RUNTA_API_URL/v2/agents/$AGENT_ID/runs/$RUN_ID/events?after=-1"

The stream emits run.status and pi.event events and closes after a terminal run state. Fetch the run to obtain its public response:

Terminal window
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $RUNTA_TOKEN" \
"$RUNTA_API_URL/v2/agents/$AGENT_ID/runs/$RUN_ID" |
jq '{id, status, result, error, dsh_session_id}'

Successful runs have status: "finished" and a final result. A closed connection alone is not proof of success: check status and error. See Runs and events for reconnection, follow-ups, image input, and cancellation.

Terminal window
jq -n '{prompt: "Now calculate twice that number."}' |
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $RUNTA_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @- \
"$RUNTA_API_URL/v2/agents/$AGENT_ID/runs/$RUN_ID/follow-ups" |
jq '{id, status, parent_run_id}'

When the previous run is terminal, this returns a new run. While a run is active, a follow-up steers that run. Always use the returned id for subsequent polling or streaming.

After finishing, request deletion of the runtime and its agents:

Terminal window
curl --fail-with-body --silent --show-error -X DELETE \
-H "Authorization: Bearer $RUNTA_TOKEN" \
"$RUNTA_API_URL/v2/agents/$AGENT_ID?delete_runtime=true"

202 Accepted means deletion was requested. Poll GET /v2/runtimes/{runtime_id} with the saved RUNTIME_ID until it returns 404 if your workflow needs confirmation of control-plane removal. Export any files or artifacts you need before deletion.