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

# Agents & Automation

> Build unattended, agentic, or automated systems on Prem API: which integration to use, required config, and the operational gotchas that matter at scale.

This page is for anyone building a system that calls Prem API **without a human watching each call**: agent loops, batch jobs, evaluation harnesses, or any tool that fires many requests unattended. Unattended callers hit different failure modes than an interactive app. A truncated response, a burned rate-limit budget, or a duplicated retry may not be noticed until it has already happened many times.

> [!TIP]
>
> If you want an AI coding agent (Claude Code, Cursor, Windsurf) to help you **write** this integration, see [Use LLMs](https://docs.prem.io/use-llms.md). It loads the Prem API docs into your coding agent's context. This page is about the system you build calling Prem API, not the coding agent that helps you build it.

## Pick your integration

| | TypeScript SDK | Confidential Proxy | ZDR |
| - | - | - | - |
| **Best for** | Node.js agents, single-process automation | Polyglot agent frameworks (LangChain, Python/Go agent loops), anything already using an OpenAI or Anthropic SDK | OpenAI-compatible tools that need the ZDR model catalog |
| **Encryption** | In-process | A local HTTP process encrypts/decrypts for you | Not confidential |
| **Code changes** | Use `@premai/api-sdk` instead of `openai` | Point `baseURL` at the proxy | Point a Chat Completions client at `https://gateway.prem.io/openai` |

> [!WARNING]
>
> The TypeScript SDK and Confidential Proxy are the confidential paths. ZDR
> does not provide enclave confidentiality. Use ZDR only when its model
> catalog is more important than confidential processing.

See [Developer Experience](https://docs.prem.io/developer-experience.md) for both, in detail. For an agent that runs continuously, run the Confidential Proxy as a **background daemon** rather than in the foreground:

```bash theme={"system"}
confidential-proxy start --compat openai --kek "$CLIENT_KEK"
confidential-proxy status
```

See [Confidential Proxy](https://docs.prem.io/confidential-proxy.md#run-the-proxy-as-a-daemon) for the full daemon lifecycle (`start` / `stop` / `status`, PID and log files, graceful shutdown).

## Required configuration

Both confidential integration paths need the same four values. Set them once in the environment where the agent runs, not for each call:

| Variable | Used by | Description |
| - | - | - |
| `PREM_API_KEY` | Both | Your API key. See [API Keys](https://docs.prem.io/api-keys.md). |
| `CLIENT_KEK` | Both | A 32-byte key encoded as 64 hexadecimal characters. You generate and keep it. See [Encryption](https://docs.prem.io/encryption.md). |
| `PROXY_URL` | Both | The Prem API Gateway endpoint. |
| `ENCLAVE_URL` | Both | The enclave endpoint. |

Get the current `PROXY_URL` / `ENCLAVE_URL` values from [`dashboard.prem.io/endpoints.json`](https://dashboard.prem.io/endpoints.json) at deploy time rather than hardcoding them.

ZDR uses the same `PREM_API_KEY` at `https://gateway.prem.io/openai`. See [ZDR overview](https://docs.prem.io/zdr/overview.md) for the ZDR setup.

## Gotchas that only show up at automation scale

These are easy to miss in a one-off script and expensive to miss in a loop that runs thousands of times.

> [accordion] Reasoning is on by default and is billed
>
> Reasoning models generate a chain-of-thought before every answer unless you turn it off.
> Those tokens are billed, count against your rate limit, and share the same inference's token budget as the visible answer. Reasoning can consume a tight `max_completion_tokens` value and leave `message.content: null`.
>
> Default to the lowest `reasoning_effort` value that the model family accepts in automated pipelines unless you explicitly consume the reasoning trace. See [Models & Pricing](https://docs.prem.io/models-and-pricing.md#reasoning-effort) for the values that each family accepts.

> [accordion] Concurrent requests have a limit for each API key
>
> Prem limits the number of inference requests that one API key can process at the same time. The limit applies to every inference endpoint. A call above the limit returns `429` with:
>
> ```json theme={"system"}
> {"status": 429, "error": "Concurrent request limit reached. Your limit allows 5 concurrent request(s). Wait for ongoing requests to complete, or contact us for higher limits."}
> ```
>
> The limit is most visible on the encrypted `/rvenc/chat/completions` endpoint, which the TypeScript SDK uses. That endpoint always responds over `text/event-stream`, even when you do not set `stream: true`. A call to it holds its slot until the stream closes. See [Tiers](https://docs.prem.io/tiers.md#concurrent-requests). If your agent sends calls in parallel on one key, send them in sequence or supply a different API key to each worker.

> [accordion] 429 responses don't all look the same
>
> Some `429` responses have a structured body and a `Retry-After` header. Others, such as a rate limit upstream of Prem, return a generic body with no `Retry-After` header. Branch on the HTTP status code, not the body shape. Use your own exponential backoff when the header is not there. See [Rate limits](https://docs.prem.io/rate-limits.md#other-429-responses).

> [accordion] Retries need to be idempotent
>
> An agent that retries blindly after a timeout or a `5xx` can duplicate the underlying action (a file upload, a resource creation). Send an `Idempotency-Key` header so a retried request has the same effect as the original. See [Idempotency](https://docs.prem.io/idempotency.md).

> [accordion] Check finish\_reason and content
>
> A `null` or empty `message.content` is not necessarily a failed call. If `finish_reason` is `"length"`, reasoning, a long answer, or both consumed the token budget. Treat it as truncation and retry with a larger `max_completion_tokens` or a lower `reasoning_effort`, not as an empty result to discard.

## A request shaped for unattended use

```typescript theme={"system"}
import createRvencClient from "@premai/api-sdk";

const client = await createRvencClient({
  apiKey: process.env.PREM_API_KEY,
  clientKEK: process.env.CLIENT_KEK,
});

const response = await client.chat.completions.create({
  model: "qwen38-27b",
  messages: [{ role: "user", content: "Summarize this log file." }],
  reasoning_effort: "low",       // reduce reasoning unless you consume it
  max_completion_tokens: 4096,    // headroom for the answer
}, {
  headers: { "Idempotency-Key": crypto.randomUUID() }, // safe to retry
});

const choice = response.choices[0];
if (choice.finish_reason === "length") {
  // Truncated: raise max_completion_tokens or retry; do not treat as empty.
}
console.log(choice.message.content);
```

## Before you deploy

* [ ] `reasoning_effort` set deliberately (the lowest value the model family accepts, or a value you've budgeted `max_completion_tokens` for)
* [ ] Retries use exponential backoff and don't assume `Retry-After` is present
* [ ] Idempotency keys on any retried write
* [ ] Concurrent calls on the same API key are serialized, or spread across multiple keys
* [ ] Every response checks `finish_reason` before treating `content` as final
* [ ] `support_id` is logged on every error for support escalation

> [!NOTE]
>
> This checklist is agent-specific. For the full production checklist (key management, tiers, attestation), see [Production Checklist](https://docs.prem.io/production-checklist.md).

## Related

> [card] [Tiers](https://docs.prem.io/tiers.md)
>
> The request, token, and audio limits of each tier.

> [card] [Rate limits](https://docs.prem.io/rate-limits.md)
>
> Retry code, the 429 shapes, and non-standard 429 bodies.

> [card] [Idempotency](https://docs.prem.io/idempotency.md)
>
> Make retries safe with the Idempotency-Key header.

> [card] [Confidential Proxy](https://docs.prem.io/confidential-proxy.md)
>
> Daemon mode, config, and connecting any language.

> [card] [OpenCode](https://docs.prem.io/guides/opencode.md)
>
> Connect OpenCode to Prem API through the local proxy.

> [card] [OpenClaw](https://docs.prem.io/guides/openclaw.md)
>
> Configure a Prem-backed OpenClaw provider and its tool boundary.

> [card] [Hermes Agent](https://docs.prem.io/guides/hermes.md)
>
> Use an explicit Chat Completions transport through Prem.

> [card] [Goose](https://docs.prem.io/guides/goose.md)
>
> Connect Goose's built-in OpenAI provider to Prem.

> [card] [Cursor compatibility](https://docs.prem.io/guides/cursor.md)
>
> Review why Cursor's provider override is not a confidential local path.

> [card] [Codex CLI compatibility](https://docs.prem.io/guides/codex-cli.md)
>
> Review the current Responses API protocol mismatch.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.