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

# Configuration

> Every init() option, explained with examples and rationale

# Configuration

This page is the long-form walkthrough of how to configure the SDK and the dashboard for your workload. For quick lookup of types and defaults, see [SDK API reference](/reference/sdk-api).

## Where configuration lives

Arclasp configuration lives in two places:

1. **`arclasp.init()` in your application** — backend connection, timeouts, retries, sanitization, and approval fallback/timeout settings. Pass values as keyword arguments.
2. **Dashboard at `app.proofrail.dev`** — the org's enforced policy thresholds, approvers, agent registry, kill switch, budget configuration.

The SDK does not currently read configuration from environment variables — every value must be passed to `init()`. If you want to keep secrets like `api_key` out of your code, read them from your own env var or secrets manager and pass the value to `init()` yourself.

## Minimal configuration

The smallest viable init against hosted Arclasp:

```python theme={null}
import arclasp

arclasp.init(api_key="prail_...", backend_url="https://api.proofrail.dev")
```

`backend_url` defaults to `http://localhost:8000`, so pass it explicitly for hosted use. For a real workload you'll probably want at least:

```python theme={null}
import os
import arclasp

arclasp.init(
    api_key=os.environ["ARCLASP_API_KEY"],   # read it yourself
    backend_url="https://api.proofrail.dev",
    environment="production",
    fallback_approvers=["lead@company.com"],
)
```

The `ARCLASP_API_KEY` env var here is a convention you control — the SDK doesn't look for it automatically.

## Environment tagging

`environment="production"` (or `"staging"`, `"development"`) tags every chain with that environment. The dashboard filters chains by environment, so you can keep production and staging audit trails separate without separate accounts.

The default is `"production"`. Don't leave this as the default if you're also running locally — your test runs will show up alongside real production activity.

A common pattern:

```python theme={null}
import os
import arclasp

arclasp.init(
    api_key=os.environ["ARCLASP_API_KEY"],
    environment=os.environ.get("APP_ENV", "development"),
)
```

## Financial thresholds

Two thresholds, both in USD:

```python theme={null}
# Per-chain cumulative override — actually reaches the backend.
# Must be set before the chain starts (before entering `async with`).
chain = arclasp.Chain("high-value-workflow")
chain.add_financial_threshold(usd=2000.0)

async with chain:
    ...
```

**Single-transaction threshold** — any one action with a top-level `amount`, `amount_usd`, or `value` key exceeding this requires approval. Enforced server-side; the default is \*\*$5,000** for a fresh organization with no custom policy. This is what the [quickstart](/quickstart)'s $6,000 example relies on.

<Note>
  `financial_approval_threshold_usd` passed to `arclasp.init()` does **not** currently change the backend-enforced threshold — it only fed the deprecated local fast-path, which governed execution no longer uses. The threshold that's actually enforced comes from your organization's policy configuration on the backend (default \$5,000). There is currently no customer-facing dashboard control to change it from the default.
</Note>

**Cumulative chain threshold** — sum of financial values across the chain. Backend default: \$10,000. Per-chain, you can override it before the chain starts with `chain.add_financial_threshold(usd=...)` (or `Chain(policy_config={...})`) — this value *is* sent to the backend as part of chain creation. See [SDK API](/reference/sdk-api) for `add_financial_threshold()`.

A hard-deny threshold (\$50,000 cumulative) sits above these — it applies to cumulative chain financial exposure, not a single transaction. Above that, the action is denied outright with no approval option. This threshold is currently a fixed value in the policy engine, not configurable via `init()`, per-chain `policy_config`, or the dashboard.

## External domain allowlist

```python theme={null}
arclasp.init(
    api_key="...",
    external_domains_allowlist=["clients.com", "vendor.com", "*.example.com"],
)
```

Domains in this list are considered "internal" for the purposes of exfiltration checks. Sending data to allowlisted domains doesn't trigger approval; sending to non-allowlisted domains does — governed by the org's backend policy configuration.

Wildcard subdomains are supported (`*.example.com` matches `api.example.com`, `mail.example.com`, etc.).

<Note>
  Like `financial_approval_threshold_usd`, this list is not currently sent to the backend when passed to `arclasp.init()` — it only fed the deprecated local fast-path. The enforced allowlist lives in your organization's backend policy configuration.
</Note>

## High-risk agents

```python theme={null}
arclasp.init(
    api_key="...",
    high_risk_agents=["payment-agent", "deploy-agent", "data-export-agent"],
)
```

Every action by these agents requires approval, regardless of what the action is. Use this for agents that have access to high-stakes tools and shouldn't run unsupervised.

The dashboard's agent registry independently supports marking an agent's `risk_tier` as `high`, which the backend does enforce. The SDK-side `high_risk_agents` list on `init()` is not currently sent to the backend and, like the thresholds above, only fed the deprecated local fast-path — use the dashboard agent registry for enforced high-risk-agent behavior.

## Approval timeout and fallback

```python theme={null}
arclasp.init(
    api_key="...",
    default_approval_timeout_hours=24,
    fallback_approvers=["lead@company.com", "cto@company.com"],
)
```

**Timeout** — approvals expire and auto-deny after this many hours. Default 24. Use a short timeout (`0.25` for 15 minutes) for chatbots and customer-facing workflows; a long timeout (`168` for 7 days) for batch jobs that can wait.

**Fallback approvers** — if no primary approver responds in half the timeout window, the approval escalates to this list. Default empty (no fallback).

If you only need fallback (no specific primary list), the SDK uses your organization's full approver list as primary and the configured list as fallback.

## Failure handling: backend unavailability always fails closed

```python theme={null}
arclasp.init(
    api_key="...",
    backend_timeout_seconds=5.0,
)
```

When the SDK can't reach the backend within `backend_timeout_seconds` (after retries), `record_agent_action()` raises `BackendUnavailableError` — the action does **not** execute. This is true regardless of `fail_mode` / `fail_modes`.

`fail_mode="allow"` (or any `fail_modes` entry set to `"allow"`) is accepted for call-signature compatibility but is deprecated and ineffective: the SDK emits a `DeprecationWarning` and still fails closed. There is no local offline buffering or "proceed and sync later" path in governed execution — every action requires an authoritative backend response.

Plan for this in latency-sensitive or flaky-network deployments by raising `backend_timeout_seconds` and `max_retries` rather than relying on a fail-open mode.

## Payload sanitization

Arclasp uses two separate lists for redacting sensitive data — one matches on field names, the other on value prefixes.

```python theme={null}
arclasp.init(
    api_key="...",
    sensitive_field_patterns=["internal_user_id", "customer_dob"],
    sensitive_value_patterns=["acme_token_"],
    max_payload_string_length=2000,
)
```

**`sensitive_field_patterns`** — field-name substrings (case-insensitive) that get redacted as `"[REDACTED]"`. The SDK iterates over dict keys and redacts any key whose name contains one of these substrings. Default list:

```
["api_key", "password", "secret", "_token", "credit_card", "ssn", "private_key"]
```

**`sensitive_value_patterns`** — string-value prefixes that get redacted. The SDK uses `str.startswith()` to match string values and redact anything beginning with one of these. Default list:

```
["sk_", "pk_", "ghp_", "hf_", "eyJ", "AKIA", "prail_"]
```

These two lists cover different attack vectors. Field patterns catch obvious cases (a `password` field in a payload). Value patterns catch leaked credentials in places they shouldn't be (an OpenAI key accidentally pasted into a payload value, or — critically — an Arclasp key starting with `prail_` being logged back through the SDK by mistake).

Custom patterns you pass via these kwargs are appended to the defaults, not replacing them.

**`max_payload_string_length`** — strings longer than this are truncated before sending. Default 1000 characters. Raise it if you need richer payloads in your audit trail; lower it if your payloads are huge (transcripts, large JSON blobs) and bandwidth matters.

Raw payloads are never persisted by Arclasp — only the sanitized version reaches storage. If you redact something locally, it's gone for good from our side.

## Fast-path local evaluation (deprecated, no effect)

```python theme={null}
arclasp.init(
    api_key="...",
    enable_local_fast_path=True,  # default — deprecated, no effect
)
```

`enable_local_fast_path` is deprecated. Setting it to `True` emits a `DeprecationWarning` at `init()` time and does nothing — governed `record_agent_action()` execution always requires backend authority now; there is no local decision path. Every action goes to the backend for evaluation. The parameter is retained only so existing `init()` calls don't break.

## Backend URL override

```python theme={null}
arclasp.init(
    api_key="...",
    backend_url="https://api.proofrail.dev",  # hosted Arclasp
)
```

Default: `http://localhost:8000`, for local development. You must pass `backend_url="https://api.proofrail.dev"` explicitly to reach hosted Arclasp — omitting it against a hosted example is the most common setup mistake. Override for:

* **Hosted Arclasp** — `https://api.proofrail.dev`
* **Testing** against a staging deployment, if you have one
* **Local development** with the backend running on `http://localhost:8000` (the default) or whatever port your local backend uses

## Chain metadata

The `metadata` parameter on `arclasp.Chain(...)` accepts arbitrary JSON-serializable key/value pairs and stores them on the chain record. The SDK treats this as opaque — it does not interpret specific keys to override SDK config.

```python theme={null}
async with arclasp.Chain(
    "high-stakes-workflow",
    metadata={
        "team": "platform",
        "workflow_version": "2.1.0",
        "trace_id": "req_abc123",
    },
) as chain:
    ...
```

Metadata appears in the dashboard chain detail view and in the chain's receipt. Useful for cross-referencing with your own systems but not for changing SDK behavior on a per-chain basis.

If you need different approval timeouts or approver lists for different workflows, initialize the SDK once per workflow boundary with the appropriate config, or use `chain.add_financial_threshold()` for a per-chain financial-threshold override (see above).

## Custom policies

Beyond the org-wide backend defaults, your organization can create a named policy record in the dashboard at `/dashboard/policies`, with a `mode` of `enforce`, `shadow`, or `disabled`:

* **`enforce`** — decisions are authoritative. Default for new policies.
* **`shadow`** — the pipeline runs but always returns `allow`; the decision it would have made is logged for later review.
* **`disabled`** — the pipeline is skipped entirely for that policy.

The dashboard does not currently expose a customer-facing rule editor, JSON matching DSL, or arbitrary predicate builder — policy configuration today is the mode control plus the org-wide threshold defaults, not free-form rule authoring or per-chain-name matching. See [Policies](/concepts/policies) for what the default policy set covers without any custom policy at all.

When a policy matches, the matching `policy_name` and `decision_reason` appear in the `PolicyDecision` returned from `record_agent_action`. For denials, they're on the raised `ActionDeniedError`.

## Common configurations

A few starting points. Note that backend unavailability always fails closed regardless of `fail_mode` (see above) — these examples focus on what's actually configurable client-side today.

**Solo developer testing, hosted backend**

```python theme={null}
import os
import arclasp

arclasp.init(
    api_key=os.environ["ARCLASP_API_KEY"],
    backend_url="https://api.proofrail.dev",
    environment="development",
)
```

**Production service with a tight per-chain financial threshold**

```python theme={null}
import os
import arclasp

arclasp.init(
    api_key=os.environ["ARCLASP_API_KEY"],
    backend_url="https://api.proofrail.dev",
    environment="production",
    default_approval_timeout_hours=4,
    fallback_approvers=["cto@company.com"],
)

chain = arclasp.Chain("checkout")
chain.add_financial_threshold(usd=500.0)  # tighter than the org default

async with chain:
    ...
```

**High-latency network — raise timeouts and retries instead of relying on fail-open**

```python theme={null}
import os
import arclasp

arclasp.init(
    api_key=os.environ["ARCLASP_API_KEY"],
    backend_url="https://api.proofrail.dev",
    environment="production",
    backend_timeout_seconds=15.0,
    max_retries=5,
)
```

## Where to go next

<CardGroup cols={2}>
  <Card title="SDK API reference" icon="code" href="/reference/sdk-api">
    Type signatures and method docs.
  </Card>

  <Card title="Exceptions" icon="triangle-exclamation" href="/reference/exceptions">
    How configuration choices surface as errors.
  </Card>

  <Card title="Policies" icon="shield" href="/concepts/policies">
    Concept page on how policies get evaluated.
  </Card>

  <Card title="Human approval" icon="user-check" href="/guides/human-approval">
    Approval timeouts and fallback in practice.
  </Card>
</CardGroup>
