> ## 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](/use-llms). 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.
</Tip>

## Pick your integration

|                  | TypeScript SDK                            | Confidential Proxy                                                                                              | Router (Beta)                                                      |
| ---------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| **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 broader Router 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://router.prem.io/v1`     |

<Warning>
  The TypeScript SDK and Confidential Proxy are the confidential paths. Prem
  Router uses a separate API key and does not provide enclave
  confidentiality. Use Router only when its broader model catalog is more
  important than confidential processing.
</Warning>

See [Developer Experience](/developer-experience) 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](/confidential-proxy#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](/api-keys).                                                                     |
| `CLIENT_KEK`   | Both    | A 32-byte key encoded as 64 hexadecimal characters. You generate and keep it. See [Encryption](/encryption). |
| `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.

Router uses `PREM_ROUTER_API_KEY` instead. See [Router custom
providers](/router/integrations) for harness-specific configuration.

## 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.

<AccordionGroup>
  <Accordion title="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 `reasoning_effort: "none"` in automated pipelines unless you explicitly consume the reasoning trace.
  </Accordion>

  <Accordion title="One active stream per API key on the encrypted endpoint">
    The encrypted `/rvenc/chat/completions` endpoint (used by the TypeScript SDK) always responds over `text/event-stream`, even when you don't set `stream: true` in your request. If a second call comes in on the same API key while one is still in flight, it can return `429` with:

    ```json theme={"system"}
    {"status": 429, "error": "You already have an active chat stream. Please wait for it to complete or try again in a few moments."}
    ```

    This is separate from the per-tier concurrent-request limits in [Rate limits](/rate-limits). If your agent parallelizes work on the same key, serialize calls per key or use a distinct API key per concurrent worker.
  </Accordion>

  <Accordion title="429 responses don't all look the same">
    Some `429`s come with a structured body and a `Retry-After` header. Others, including throttling applied upstream of the gateway, return a generic body with no `Retry-After` header. Branch on the HTTP status code, not the body shape, and fall back to your own exponential backoff when the header is missing. See [Rate limits](/rate-limits#non-standard-429-responses).
  </Accordion>

  <Accordion title="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](/idempotency).
  </Accordion>

  <Accordion title="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.
  </Accordion>
</AccordionGroup>

## 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: "glm-5.2",
  messages: [{ role: "user", content: "Summarize this log file." }],
  reasoning_effort: "none",       // skip 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 (`none` by default, 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](/production-checklist).
</Note>

## Related

<CardGroup cols={2}>
  <Card title="Rate limits" icon="wave-pulse" href="/rate-limits" arrow="true">
    Limits by tier, retry code, and non-standard 429 bodies.
  </Card>

  <Card title="Idempotency" icon="fingerprint" href="/idempotency" arrow="true">
    Make retries safe with the Idempotency-Key header.
  </Card>

  <Card title="Confidential Proxy" icon="server" href="/confidential-proxy" arrow="true">
    Daemon mode, config, and connecting any language.
  </Card>

  <Card title="OpenCode" icon="terminal" href="/guides/opencode" arrow="true">
    Connect OpenCode to Prem API through the local proxy.
  </Card>

  <Card title="OpenClaw" icon="terminal" href="/guides/openclaw" arrow="true">
    Configure a Prem-backed OpenClaw provider and its tool boundary.
  </Card>

  <Card title="Hermes Agent" icon="terminal" href="/guides/hermes" arrow="true">
    Use an explicit Chat Completions transport through Prem.
  </Card>

  <Card title="Goose" icon="terminal" href="/guides/goose" arrow="true">
    Connect Goose's built-in OpenAI provider to Prem.
  </Card>

  <Card title="Cursor compatibility" icon="code" href="/guides/cursor" arrow="true">
    Review why Cursor's provider override is not a confidential local path.
  </Card>

  <Card title="Codex CLI compatibility" icon="terminal" href="/guides/codex-cli" arrow="true">
    Review the current Responses API protocol mismatch.
  </Card>
</CardGroup>
