Files
openclaw/docs/plugins/onepassword.md
Peter Steinberger 6bb85f177f feat(onepassword): optional 1Password secrets broker plugin (#106133)
* feat(onepassword): add optional 1Password secrets broker plugin

Curated slug registry with per-item auto/approve/deny policy, plugin-approval
gating with expiring allow-always grants, SQLite audit history, onepassword
status/audit CLI, and a single-attempt op client (--cache=false, minimal env).

Closes #105924

* docs(plugins): refresh generated inventory count after rebase

* fix(onepassword): scope grants and field reads

* fix(onepassword): bound grant retention

* fix(onepassword): satisfy deadcode ratchet and hook allowlist contract

* fix(onepassword): honor live policy reloads

* refactor(onepassword): trim private exports

* test(onepassword): satisfy plugin boundaries

* test(onepassword): document temp directory boundary
2026-07-13 03:12:47 -07:00

6.8 KiB

summary, read_when, title
summary read_when title
Use the optional 1Password plugin as an audited agent secrets broker
You want agents to request curated 1Password secrets
You need per-secret approval policy and audit history
You are configuring a 1Password service account for OpenClaw
1Password secrets broker

1Password secrets broker

The bundled onepassword plugin gives agents one policy-controlled tool for reading a curated set of 1Password fields. It is disabled by default and does nothing until plugins.entries.onepassword.config is present.

This is an agent tool, not a SecretRef provider. It does not inject environment variables or resolve OpenClaw config secrets.

Security model

  • Service-account authentication only. The token stays in a local credentials file and is never accepted in openclaw.json.
  • Curated registry only. Agents can list configured slugs, but the plugin never enumerates a 1Password vault.
  • Per-slug auto, approve, or deny policy.
  • Approval grants expire. A cached value never bypasses current policy.
  • Every access attempt is recorded in OpenClaw's shared SQLite state. Audit rows include the supplied reason; keep reasons non-sensitive. The broker never copies a fetched value or the service token into an audit row.
  • After the current tool execution, OpenClaw-owned transcript persistence replaces a successful get value with redacted metadata.
  • The value is model-visible for that execution. If the model copies it into a later tool call or reply, that separate record is outside this plugin's persistence hook. Keep policies narrow and do not ask the model to echo a value.
  • The plugin invokes op once per cache miss. It does not retry rate limits or other failures.

Give the service account read access only to the vaults and items registered in the plugin config.

Before you begin

You need:

  • the 1Password CLI (op) installed on the Gateway host
  • a 1Password service account with access to the selected items
  • a dedicated service-account token file

Enable the bundled plugin:

openclaw plugins enable onepassword

Create the token directory and file under the OpenClaw state directory:

mkdir -p ~/.openclaw/credentials/onepassword
chmod 700 ~/.openclaw/credentials/onepassword
printf '%s' "$OP_SERVICE_ACCOUNT_TOKEN" > \
  ~/.openclaw/credentials/onepassword/service-account-token
chmod 600 ~/.openclaw/credentials/onepassword/service-account-token
unset OP_SERVICE_ACCOUNT_TOKEN

When OPENCLAW_STATE_DIR is set, replace ~/.openclaw with that directory. The plugin warns once when the token file is readable or writable by group or other users.

Configure registered secrets

Add plugin config to openclaw.json:

{
  "plugins": {
    "entries": {
      "onepassword": {
        "enabled": true,
        "config": {
          "vault": "Automation",
          "defaultPolicy": "approve",
          "cacheTtlSeconds": 300,
          "grantTtlHours": 720,
          "opTimeoutMs": 15000,
          "items": {
            "repository-token": {
              "item": "Repository automation token",
              "field": "credential",
              "policy": "approve",
              "description": "Token for repository automation",
            },
            "model-key": {
              "item": "Model provider key",
              "vault": "Agent credentials",
              "policy": "auto",
            },
          },
        },
      },
    },
  },
}

Slugs use lowercase letters, numbers, and hyphens, start with a letter or number, and contain at most 64 characters. A registry can contain up to 32 slugs; descriptions can contain up to 200 characters. field accepts one field label or ID, must not contain a comma, and defaults to credential. An item-level vault overrides the default vault. opBin can set an absolute path to the op executable; otherwise the plugin resolves op from PATH. Item titles must not start with a hyphen.

Use the agent tool

The tool name is onepassword.

List registered slugs:

{ "action": "list" }

The result contains only the slug, description, policy, and whether a standing grant is active. It never contains a secret value and does not query 1Password.

Request one secret:

{
  "action": "get",
  "slug": "repository-token",
  "reason": "Authenticate the requested repository operation"
}

reason is required, must be non-empty, and is limited to 300 characters. A successful get returns the value plus the configured slug, item title, and field label.

Policy tiers and approvals

  • auto: fetch immediately and audit the request.
  • deny: block and audit the request.
  • approve: use an unexpired standing grant, or ask a human to allow once, always, or deny.

Allow once authorizes only the current tool call. Allow always writes a standing grant for that agent and slug to SQLite; other agents must receive their own approval. OpenClaw offers allow always only when the caller has a concrete agent identity. The grant expires after grantTtlHours, which defaults to 720 hours. An unresolved or timed-out approval denies the request; the maximum approval wait is 600 seconds. The plugin retains up to 1,024 standing grants; at that bound, the oldest grant is evicted and its agent must approve the next access.

The in-memory cache defaults to 300 seconds and is bounded by the configured slug registry. Set cacheTtlSeconds to 0 to disable it. Policy is evaluated before every cache lookup, and cache hits are audited. Runtime config reloads take effect at each policy and execution boundary; disabling the plugin or removing, denying, or retargeting a slug invalidates pending authorization and cached values.

Inspect status and audit history

Show readiness and registry counts:

openclaw onepassword status

This reports whether the token file exists, whether op resolved and its path, the registered item count, and per-policy counts. It never reads or prints the token or secret values.

Show the 50 most recent audit rows:

openclaw onepassword audit
openclaw onepassword audit --limit 100

Rows are newest first and show timestamp, agent, slug, outcome, and a truncated reason. The reason is stored as supplied; the broker never adds the fetched value to the audit log.

1Password CLI behavior

Each cache miss runs op item get with the configured item, vault, and exact field selector, JSON output, a bounded timeout, and --cache=false. The child receives only that field rather than the full item. Only OP_SERVICE_ACCOUNT_TOKEN and HOME are present in the child environment.

The plugin makes one attempt. RATE_LIMITED errors should be handled by waiting before a later agent request; the plugin does not create an automatic retry loop. Other stable error codes distinguish missing tokens or binaries, missing items or fields, authentication failures, timeouts, and other op failures.