# Identity Files

> Store Thalovant client credentials, endpoint defaults, protocol flags, and broker credentials for SDK use.

Source: https://docs.thalovant.com/developers/identity-files/

---
An identity file is private setup material for one client. It tells the SDK how to authenticate, which protocols are enabled, and where to connect.

Create identities in Thalovant, then give each deployed client only the identity it needs.

## Recommended Local Config

For local development, put SDK credentials in a protected YAML file:

```bash
install -d -m 700 ~/.config/thalovant
$EDITOR ~/.config/thalovant/config.yaml
chmod 600 ~/.config/thalovant/config.yaml
```

The SDKs read `~/.config/thalovant/config.yaml` by default. If `XDG_CONFIG_HOME` is set, they read `$XDG_CONFIG_HOME/thalovant/config.yaml`. On Windows, they use `%APPDATA%\Thalovant\config.yaml`.

```yaml
version: 1
profile: prod
profiles:
  prod:
    identity:
      access_key: client-access-key
      password: client-password
      site_id: demo-agent
      default_master: https://jokes.thalovant.io
      default_port: 443
      default_path: /public
      data_plane_endpoints:
        wss: wss://jokes.thalovant.io/public
        https: https://jokes.thalovant.io/public
        mqtt: mqtts://mqtt.thalovant.com:8883
      protocols:
        wss: { enabled: true }
        http: { enabled: true }
        mqtt: { enabled: true }
      mqtt:
        endpoint: mqtts://mqtt.thalovant.com:8883
        username: client-access-key
        password: client-broker-password
        topic_prefix: <namespace>/<hub-id>/<client-id>
        tls: true
```

You can add more profiles under `profiles`, then choose one in code.

| SDK | Load default profile | Load named profile |
| --- | --- | --- |
| Python | `ThalovantClient.from_config()` | `ThalovantClient.from_config(profile="prod")` |
| Node.js | `await ThalovantClient.fromConfig()` | `await ThalovantClient.fromConfig({ profile: "prod" })` |
| Go | `thalovant.NewClientFromConfig("", "")` | `thalovant.NewClientFromConfig("", "prod")` |
| Rust | `Client::from_config(None)` | `Client::from_config(Some("prod"))` |

  On Linux and macOS, SDKs reject config files and raw JSON identity files that are readable or writable by group or other users. Use `chmod 600` before loading local identity material.

## At A Glance

| Field | Required | Purpose |
| --- | --- | --- |
| `access_key` | Yes | Public identifier for the client. |
| `password` | Yes | Secret used by the client during auth. |
| `site_id` | Recommended | Stable client site, device, service, or runtime label. |
| `data_plane_endpoints` | Recommended | Explicit WSS, HTTPS, and MQTT addresses. |
| `protocols` | Recommended | Protocol availability for this hub. |
| `mqtt` | MQTT only | Per-client broker endpoint, username, password, and topic scope. |

Hubs no longer issue a `crypto_key`. Encryption comes from the SDK's own authenticated session, keyed from the identity's `password`. Current SDKs accept and ignore `crypto_key` in older identity files. The identity still needs a valid password and an enabled endpoint.

## Raw Identity File

```json
{
  "access_key": "client-access-key",
  "password": "client-password",
  "site_id": "demo-agent",
  "default_master": "https://jokes.thalovant.io",
  "default_port": 443,
  "default_path": "/public",
  "data_plane_endpoints": {
    "wss": "wss://jokes.thalovant.io/public",
    "https": "https://jokes.thalovant.io/public",
    "mqtt": "mqtts://mqtt.thalovant.com:8883"
  },
  "protocols": {
    "wss": { "enabled": true },
    "http": { "enabled": true },
    "mqtt": { "enabled": true }
  },
  "mqtt": {
    "endpoint": "mqtts://mqtt.thalovant.com:8883",
    "username": "client-access-key",
    "password": "client-broker-password",
    "topic_prefix": "<namespace>/<hub-id>/<client-id>",
    "tls": true
  }
}
```

Raw JSON identity files are still supported. Use them for downloaded single-client identities or securely mounted credential files. Use the YAML config when you want named local profiles.

If you keep `_identity.json` on a laptop, workstation, or VM, restrict it before the SDK reads it:

```bash
chmod 600 _identity.json
```

Python, Node.js, Go, and Rust SDKs reject local identity files with group or world access rules on Linux and macOS. In containers, mount the file from a secret store with owner-only permissions.

The SDKs also support environment variables for container and CI usage. Prefer secret stores for production deployments.

## Saved Keys

The identity file and the SDK's saved keys work together. Keep both across application and container restarts:

| Material | Why it must survive |
| --- | --- |
| Client key | The hub recognises this client by it after the first connection. Replacing it on every start makes the client a stranger each time. |
| Recorded hub identities | The SDK uses these to recognise the hub on reconnect and to reject an unexpected one. |
| Cached credentials, when used | These save deriving from the password on every connection. Protect them like the password. |

Use a private, writable, persistent directory or the SDK's platform storage provider. An identity file mounted read-only is useful for credentials, but the SDK also needs writable storage for its own saved keys. A custom identity-file path does not by itself relocate that state. Language-specific directory options and platform requirements are listed on the [SDK pages](/developers/sdks/).

For server-side Node and MCP, the saved keys live next to the config file: `~/.config/thalovant` by default, `$XDG_CONFIG_HOME/thalovant` when that variable is set, or `%APPDATA%\Thalovant` on Windows. Preserve the directory as a unit. MCP has no per-tool option for it.

Node writes its saved keys atomically across processes. Damaged saved keys stop the operation without resetting what was saved. If a crashed process leaves `.noise-state.lock` behind, confirm the process has stopped before removing only the lock file, and keep the key files. This lock does not coordinate live hub sessions or browser tabs.

Damaged saved hub identities stop authentication without overwriting the original state. For SDKs that store them as hexadecimal, upper- and lowercase encodings of the same key identify the same hub.

A failed connection is not a reason to delete saved keys or generate new ones. Check the identity password, the endpoint, and that the original client key is available. Confirm a changed hub identity with the hub owner before accepting it.

## Safe Handling

1. **Create one identity per active client process.** Give parallel services, MCP processes, and devices separate identities. HTTP and MQTT sessions use identity-scoped state, so sharing credentials can make clients consume or close each other's session.
2. **Store it as a secret.** Use a secret store, protected environment, or private runtime volume.
3. **Keep access narrow.** Grant only the access rules that client needs.
4. **Rotate on exposure.** Recreate the client identity if a file or secret is copied to the wrong place.
5. **Review stale clients.** Connections can show identity review when a client has not reported presence for a long time.
6. **Refresh after protocol changes.** Create or download a fresh identity after enabling HTTPS or MQTT.

## Stale Identity Review

The dashboard marks a connection for identity review when no presence has been seen for an extended period. Review means "confirm the device or runtime is still expected" before trusting the identity again.

When the dashboard recommends quarantine, use **Quarantine identity** to disable that client’s access. Rotate or recreate the identity before restoring access.

## Client Metadata

Use `site_id` and request context together:

| Metadata | Best use |
| --- | --- |
| `site_id` | Stable runtime, device, room, service, or deployment label. |
| `session_id` | Conversation, workflow, user journey, or trace group. |
| `request_id` | Single request trace through logs and support records. |
| Context | User, platform, app version, locale, or flow details. |

  The identity says who the client is. Request context says what this request is doing right now.

## Do Not Store

  
    Do not commit identity files, copied setup commands, or raw environment files.
  
  
    Do not ship long-lived client secrets in JavaScript served to users. Use [SDK origins](/developers/sdk-origins/) for reviewed browser domains, and keep secrets on a backend.
  
  
    Redact passwords, access keys, crypto keys, broker passwords, and setup material before logging.
  
  
    Share request IDs, hub names, and visible errors instead of setup material.
