Tarka/Docs/Control API/Provisioned resources
PreviewControl API · Provisioning

Desired-state compute resources

Record typed desired state, keep a stable resource identity, and inspect reconciliation status through organization-scoped resource reads.

Preview contract, entitlement-gated products.

Managed inference desired state is published for approved accounts. Agent Hosts and Batch Jobs additionally require an approved agents orjobs entitlement. Submitting a product-access request does not bypass that gate.

Apply semantics

Name identifies desired state within a resource type

Managed inference and Agent Host creation methods are apply operations. The tuple (org_id, resource_type, name) is unique. Reusing it updates the stored spec, returns the same resource ID, resets lifecycle state to pending, and creates an audit entry.

ProvisionedResourceshared response
{
  "id": "448a...",
  "org_id": "9df4...",
  "resource_type": "agent",
  "name": "research-agent",
  "status": "pending",
  "namespace": "",
  "external_url": "",
  "spec": {
    "definition": "compose",
    "template_id": "openclaw",
    "template_version": "2026.2.6-tarka.4",
    "tier": "core",
    "service_count": 2,
    "active_revision": 1,
    "secret_variable_names": ["AUTH_PASSWORD", "OPENCLAW_GATEWAY_TOKEN"]
  },
  "status_detail": {},
  "created_at": "2026-08-30T14:00:00Z",
  "updated_at": "2026-08-30T14:00:00Z"
}
NameDNS label

Lowercase letters, digits, and hyphens; 1–63 characters; start and end with alphanumeric.

Typed fields winstable contract

Required typed fields override conflicting keys supplied in the free-form spec object.

Status detailmachine-readable

Controllers may attach provider state or stable failure information without changing desired spec.

Managed inference

Apply an inference service

model_alias must exist in the active model registry. Replica counts must be non-negative, and a non-zero max_replicas must be greater than or equal to min_replicas.

Inference servicePOST
curl -X POST \
  "https://tarka.rest/control/v1/orgs/$TARKA_ORG_ID/inference-services" \
  -H "Authorization: Bearer $TARKA_ACCOUNT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name":"himalaya-service",
    "model_alias":"himalaya-q8",
    "min_replicas":0,
    "max_replicas":2,
    "spec":{"region":"eu-central"}
  }'

The canonical organization route is /orgs/{org_id}/inference-services. The compatibility binding /inference-services remains available when org_id is supplied in the request body.

Send the intended request with dry_run: true to receive spec.compute_quote. Review its billing currency, exact allocated memory, hourly rate and next-lease hold. Submit the same request with dry_run: false and accepted_quote_id within five minutes. The console requires this confirmation. Existing EU API clients may omit the quote; technical core and pro sizes are not subscription offers.

Model calls and any separately accepted data policy are additional. Running hosts renew paid leases. See quotes, reservations and usage policy.

By request

Apply an Agent Host stack

Choose exactly one template_id, inline compose_yaml, or legacy single-container image. OpenClaw, Hermes, and Onyx expose runtime defaults, gateways, and variables through the template catalog. Reusing the same name creates an immutable revision.

Template catalogGET
curl \
  "https://tarka.rest/control/v1/agent-host-templates" \
  -H "Authorization: Bearer $TARKA_ACCOUNT_TOKEN"
Agent Host price previewdry_run: true
# Upload secrets through the authenticated console handoff first.
# The bundle UUID is safe for the assistant to handle; secret values are not.
jq -n \
  --arg bundle "$TARKA_SECRET_BUNDLE_ID" \
  '{
    name: "research-agent",
    template_id: "openclaw",
    tier: "core",
    dry_run: true,
    secrets_bundle_id: $bundle,
    runtime: {primary_model_alias: "deepseek-v4.1-flash-eu"}
  }' |
curl -X POST \
  "https://tarka.rest/control/v1/orgs/$TARKA_ORG_ID/agent-hosts" \
  -H "Authorization: Bearer $TARKA_ACCOUNT_TOKEN" \
  -H "Content-Type: application/json" \
  --data @-
Composecompose_yaml

Multi-service stacks of prebuilt images with health checks, volumes, tmpfs, resources, and routes. Git builds inside Agent Hosts are disabled; build locally or in your own CI and push to Tarka's registry first.

Variablessecret: true

Secret values are encrypted separately and never returned in ProvisionedResource.spec.

Runtimeprimary_model_alias

Select the host's chat model, supported template gateways, and custom Compose services that receive managed discovery variables.

Public routex-tarka.routes

Declare path/service/port mappings or one public_service andpublic_port override.

Redacted editable configurationGET
curl \
  "https://tarka.rest/control/v1/orgs/$TARKA_ORG_ID/agent-hosts/$AGENT_HOST_ID/configuration" \
  -H "Authorization: Bearer $TARKA_ACCOUNT_TOKEN"

Secret values are empty in this response. A secret with preserve_existing: true can be carried into the next revision without returning its plaintext.

Signal QR pairingHermes · ready host
curl \
  "https://tarka.rest/control/v1/orgs/$TARKA_ORG_ID/agent-hosts/$AGENT_HOST_ID/gateways/signal/pairing" \
  -H "Authorization: Bearer $TARKA_ACCOUNT_TOKEN"
Delete Agent HostDELETE
curl -X DELETE \
  "https://tarka.rest/control/v1/orgs/$TARKA_ORG_ID/agent-hosts/$AGENT_HOST_ID" \
  -H "Authorization: Bearer $TARKA_ACCOUNT_TOKEN"
Custom Compose

Private GitHub images through REST, MCP, and Python

Put image paths such as ghcr.io/my-org/my-agent:v1 in your Compose file. Supply credentials separately in github_registry_credentials. This field is available only with compose_yaml.

Use the token owner's GitHub username and a classic PAT with read:packages, access to every referenced package, and organization SSO authorization when required. The username is not the repository or package owner. Your Tarka account token authenticates the Control API; the GitHub PAT is used only for GHCR pulls.

Named credentials and verified pulls

The console uses POST /control/v1/orgs/{org_id}/agent-host-registry-tests with the host name, a complete credentials array and every GHCR image with its Compose service. Each credential has a label, username, token and assigned services. To preserve a stored token, send its returned id and version and omit the token. Removing an entry removes that credential only after a successful test and apply.

Poll GET /control/v1/orgs/{org_id}/agent-host-registry-tests/{test_id}. When its status is succeeded, include registry_test_id in the complete host apply request. Do not combine it with github_registry_credentials. The proof expires after 30 minutes, binds to the exact service images and current credential version, and is consumed once by a successful apply. Dry runs do not consume it. Cancel queued or running tests with DELETE at the same test URL.

Configuration reads return registry_credentials containing IDs, labels, usernames, versions and service assignments only. Starting a credential test is a human action through the console or direct HTTP and is excluded from MCP. MCP can read test status and submit the verified test ID without receiving a PAT.

Compatible single-credential requests

Create or update a private-image hostREST · Python standard library
import getpass, json, os, pathlib, urllib.request

payload = {
    "name": "private-agent",
    "compose_yaml": pathlib.Path("compose.yaml").read_text(),
    "github_registry_credentials": {
        "username": os.environ["GITHUB_USERNAME"],
        "token": getpass.getpass("GitHub classic PAT: "),
    },
}
url = "https://tarka.rest/control/v1/orgs/" + os.environ["TARKA_ORG_ID"] + "/agent-hosts"
request = urllib.request.Request(url, method="POST",
    data=json.dumps(payload).encode(), headers={
        "Authorization": "Bearer " + os.environ["TARKA_ACCOUNT_TOKEN"],
        "Content-Type": "application/json",
    })
payload["dry_run"] = True
request.data = json.dumps(payload).encode()
with urllib.request.urlopen(request, timeout=60) as response:
    preview = json.load(response)
quote = preview["spec"]["compute_quote"]
print(json.dumps(quote, indent=2))
if not quote["admission"]["available"] or input("Accept this price and create? [yes/no] ") != "yes":
    raise SystemExit("Not created")
payload.update(dry_run=False, accepted_quote_id=quote["id"])
request.data = json.dumps(payload).encode()
with urllib.request.urlopen(request, timeout=60) as response:
    host = json.load(response)
print(host["id"], host["status"])

The example reads compose.yaml and prompts for the PAT without echoing it. Do not print the request or put credentials in Compose, spec, source code, logs, or chat transcripts.

Preserve, replace, and remove credentials

Apply the same host name and the complete Compose definition on each update. Tarka checks GHCR access before saving; a failed check leaves credentials and the current revision unchanged.

  • Preserve: omit github_registry_credentials. An empty object is not the preserve operation.
  • Replace: supply both username and the new token.
  • Remove: send {remove: true} after switching every GHCR image to anonymous access. Do not combine removal with a username or token.
Removal field in the complete apply requestJSON
{
  "github_registry_credentials": {
    "remove": true
  }
}

GET /control/v1/orgs/{org_id}/agent-hosts/{agent_host_id}/configuration returns only the saved username and configured status. The token is write-only, encrypted at rest, and never returned or included in revision history. The controller provides it only as an image-pull credential, never a container environment variable.

Configuration response fragmentredacted metadata
{
  "github_registry_access": {
    "username": "octocat",
    "configured": true
  }
}

Deleting a host removes its saved credentials. Removal does not revoke the PAT at GitHub or stop already running containers. Revoke the PAT at GitHub when required.

MCP

Connect your MCP client as described in MCP. Creating a host needs a connection with write access, provisioning:read provisioning:write. Set or change private GHCR credentials yourself through the console or direct HTTP; MCP rejects plaintext registry credentials. Omitted credentials preserve the host's existing pull access. Supply application secrets through a separate handoff, then pass its ID in the complete apply request and review the price before creation.

Apply through MCPtools/call parameters
{
  "name": "tarka_create_agent_host",
  "arguments": {
    "org_id": "<organization UUID>",
    "name": "private-agent",
    "dry_run": true,
    "compose_yaml": "services:\n  agent:\n    image: ghcr.io/my-org/my-agent:v1\n",
    "secrets_bundle_id": "<uploaded secret handoff UUID>"
  }
}

Read back with tarka_get_agent_host_configuration and org_id/agent_host_id. Its github_registry_access contains the same redacted metadata. A read-only MCP grant cannot set, replace, or remove credentials.

Secrets from a file or the console

Prepare a handoff with POST /control/v1/orgs/{org_id}/agent-host-secret-bundles and the host's name. Open its console_url yourself to upload a .env file or a JSON object of string values. The local secret-file helper can upload directly from your terminal using your account token in the environment. Do not have the coding agent read the file or paste its contents into chat.

The assistant reads only key names and status, then submits secrets_bundle_id with the host request. The handoff expires after one hour and is consumed only by successful admission for the same organization, name and revision. A concurrent host update requires a new handoff. Direct HTTP clients can continue sending inline secrets.

Python SDK

SDK 0.2.0 adds AgentHostGitHubRegistryCredentials and the matching redacted response type. See the Python credential examples and installable release.

For the console workflow, see Private GitHub images.

Tarka registry images

Push your local build with a Tarka credential and reference registry.tarka.rest/orgs/<organization UUID>/<repository>. Agent Hosts accept tags and pin the resolved digest; jobs require an explicit digest. The resource and image must belong to the same organization. Pull authorization is automatic; omit github_registry_credentials for Tarka images.

By request

Create a queued Batch Job

command is a non-empty argument vector. Jobs execute in US East by default after accepting a current quote. Set TARKA_JOB_IMAGE to a public or same-organization Tarka registry image pinned by digest; the example expects your image to contain Python and the evals.run module. Resources, runtime/network caps, reads and cancellation are explicit. See Batch Job availability.

Batch Jobjobs entitlement
import json, os, urllib.request, uuid

base = "https://tarka.rest/control/v1/orgs/" + os.environ["TARKA_ORG_ID"]
headers = {"Authorization": "Bearer " + os.environ["TARKA_ACCOUNT_TOKEN"],
           "Content-Type": "application/json"}
def post(path, body):
    request = urllib.request.Request(base + path, method="POST", headers=headers,
                                     data=json.dumps(body).encode())
    with urllib.request.urlopen(request, timeout=60) as response:
        return json.load(response)

resources = {"cpu_millis": 1000, "memory_mib": 1024, "ephemeral_storage_mib": 1024}
quote = post("/compute-quotes", {"product": "jobs", "location": "us-1",
    "resources": resources, "max_runtime_seconds": 60, "max_network_bytes": 1048576})
print(json.dumps(quote, indent=2))
if not quote["available"] or input("Accept this price and create? [yes/no] ") != "yes":
    raise SystemExit("Not created")
job = post("/jobs", {"name": "nightly-eval", "location": "us-1",
    "image": os.environ["TARKA_JOB_IMAGE"],  # Full Linux/amd64 image@sha256:digest.
    "command": ["python", "-m", "evals.run"], "resources": resources,
    "timeout_seconds": 60, "max_network_bytes": 1048576,
    "queue_timeout_seconds": 600, "accepted_quote_id": quote["id"],
    "idempotency_key": str(uuid.uuid4())})
print(job["id"], job["status"])
Read state

List or retrieve shared resource state

Use GET /orgs/{org_id}/resources and optional ?resource_type=inference_service, agent, job, sandbox, bucket, or git_repo. Retrieve one record with GET /orgs/{org_id}/resources/{resource_id}.

StatusMeaning
pendingDesired state is accepted and awaits reconciliation.
provisioningA controller is applying provider or cluster state.
readyThe resource is reconciled and usable.
failedReconciliation stopped; inspect status_detail.
deletingProduct-specific deletion is in progress.
deletedThe data-plane resource is removed; final control state is retained.
No generic delete is published.

Object Storage, Hosted Git, Sandboxes, and Agent Hosts have product-specific deletion methods. Managed inference has no generic delete. Batch Jobs have explicit run cancellation; read the final run state to confirm work stopped.