TL;DR
- A scoped
OP_SERVICE_ACCOUNT_TOKENper workflow purpose replaces long-lived SaaS API keys sitting in GitHub secrets — each token resolves only the credentials that purpose actually needs, from a vault scoped to it. - Every credential access is logged; rotating a key in the vault propagates to every workflow automatically; revoking a token cuts access to exactly what it could reach — small, because the vault behind it is small.
- The 1Password Python SDK resolves secrets in-process — no shell subprocess, no
opbinary, vault as a typed dependency. - Use OIDC for AWS; use a 1Password service account for everything the AWS identity plane can’t federate with.
- That’s infrastructure. Start treating it like one.
1Password recently announced 1Password Unified Access — an enterprise product positioning the vault as credential infrastructure for AI agents. Endpoint discovery, runtime credential brokering, audit logs, scoped access for autonomous workflows. They also shipped SDKs for Python, JavaScript, and Go so agents can integrate with the vault natively, in-process, without the CLI.
The announcements describe a problem worth solving. They also describe something you can build today, on a personal account, with tools that have existed since 2022.
This is the third post in an eight-post series. The first covered what 1Password can replace in a builder setup — SSH keys, git signing, AWS CLI credentials, .env files. The second covered what an AI agent can do when it operates the vault directly — reorganizing 690 credentials in one session. This one is about what the vault enables when agents need to operate everything else. The fourth goes further: 1Password as the live trust anchor in a running authentication chain.
The problem Unified Access is solving
AWS has a mature credential model. IAM roles, temporary credentials via STS, OIDC federation, resource policies. A GitHub Actions workflow can assume an IAM role directly — no stored credentials, no rotation, nothing to leak. The problem is solved at the infrastructure layer.
The SaaS layer has no equivalent.
Stripe gives you an API key — one key, broad permissions, no expiry unless you rotate it manually. OpenAI is the same. Cloudflare, Twilio, SendGrid, Notion, GitHub — all the same. Flat credentials. No scoping to a specific workflow or agent. No native audit log showing which process called it. No revocation path that doesn’t also break everything else using that key.
As autonomous workflows multiply — deploy pipelines, content agents, data sync jobs, monitoring scripts — each one eventually needs to call something in this layer. And right now, there’s no standard way to give an autonomous process auditable, revokable, scoped access to a Stripe key. You copy the key into an environment variable and hope nothing goes wrong.
Unified Access is 1Password’s enterprise answer to this. The personal account version of the same answer already exists: service accounts.
What a service account actually does
A service account is a token — one credential — that grants access to a scoped set of vault items. The decision that determines whether this pattern helps you or just relocates the problem is what you scope it to.
The instinct is to create one vault for “the project” and one token that can read all of it — fewer moving parts, one secret to manage. Resist it. That token is now exactly as dangerous as the worst credential it can reach. Scope to the workflow’s actual job instead.
Say a deploy workflow needs to verify a Stripe webhook and purge a Cloudflare cache — and nothing else. Give it a vault that holds exactly those two items:
op vault create ci-deploy
# Stripe and Cloudflare items go in here. Nothing else does.
op service-account create "ci-deploy-readonly" --vault "ci-deploy:read_items" --raw
That token goes into GitHub as a single secret: OP_SERVICE_ACCOUNT_TOKEN. The workflow uses it to pull exactly what it needs:
- name: Load credentials from 1Password
uses: 1password/load-secrets-action@v4
with:
export-env: true
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
STRIPE_SECRET_KEY: op://ci-deploy/Stripe/credential
CLOUDFLARE_API_TOKEN: op://ci-deploy/Cloudflare/credential
GitHub doesn’t know either value. It knows one token — and that token cannot resolve anything outside ci-deploy, because there’s nothing else in ci-deploy to resolve. A content workflow that also needs an OpenAI key doesn’t get a wider grant on the same token. It gets its own vault (ci-content), its own service account, scoped the same way.
The pattern:
ci-deploy workflow ci-content workflow
└── OP_SERVICE_ACCOUNT_TOKEN └── OP_SERVICE_ACCOUNT_TOKEN
scoped to ci-deploy:read_items scoped to ci-content:read_items
├── Stripe key └── OpenAI key
└── Cloudflare token (nothing else reachable)
Two vaults, two tokens, more setup than --vault "ACL:read_items" pointed at everything in one place. That’s the cost, and it’s worth paying: each token’s reach now matches the workflow’s actual need. Nothing more is reachable from either one — not because you trust the workflow not to misuse a wider grant, but because the wider grant doesn’t exist.
What this changes
Attribution. Stripe has no audit log for which process used your API key. 1Password does. Every credential access by the service account is logged — which item, when, from which workflow.
Rotation without workflow changes. Rotate the Stripe key in the vault. Every workflow that references it picks up the new value automatically. No updating GitHub secrets. No redeploying anything.
Revocation that’s actually small. If ci-deploy’s token leaks, you revoke it — and what it could reach was two items in one narrow vault, not your entire credential surface. The size of “everything it could reach” was a design decision made when the vault was scoped, not a fact you discover during incident response.
A handful of scoped secrets in CI instead of ten unscoped ones — or one that covers everything. The attack surface of your CI environment is a small set of narrowly-scoped tokens, each one bounded to a single workflow’s purpose. Not a pile of long-lived service credentials in GitHub secrets, and not a single master key wearing a service-account costume.
None of this requires Unified Access. It works today on a personal 1Password account with the existing CLI.
The SDK: 1Password as a native agent dependency
The CLI pattern works. But there’s a cleaner integration for agents written in Python, JavaScript, or Go: the 1Password SDK.
pip install onepassword-sdk
A Python agent resolves secrets directly in-process — no shell subprocess, no op binary call:
import asyncio
import onepassword
async def main():
client = await onepassword.Client.authenticate(
auth=SA_TOKEN, # service account token from environment
integration_name="my-agent",
integration_version="1.0.0",
)
# resolve any secret by op:// reference — scoped to whatever vault this token can see
stripe_key = await client.secrets.resolve("op://ci-deploy/Stripe/credential")
cloudflare_token = await client.secrets.resolve("op://ci-deploy/Cloudflare/credential")
# list items in the vault — only items this token's vault grant covers
items = await client.items.list(vault_id)
for item in items:
print(f"[{item.category}] {item.title}")
asyncio.run(main())
Tested the mechanics against a personal vault with 37 items, scoped at read_items: secret resolution works, item listing works, every item the grant covers is visible. The vault title comes back encrypted at that scope — correct behavior, not a bug; a service account reading items doesn’t need vault metadata.
That test confirmed the SDK does what it says. It says nothing about what the vault on the other end of the token should contain. A 37-item vault behind a CI token is the wrong shape for the reasons covered above — ci-deploy, with exactly the two items a deploy workflow touches, is the shape worth deploying. Test the mechanism against whatever’s convenient. Scope the real thing to the job.
The difference from the CLI: the agent doesn’t shell out. The vault client is a dependency in your code the same way a database client is. Typed responses, native async, no subprocess management. For agents that need to resolve credentials at runtime — not at deploy time — this is the right integration path.
Where AWS fits in
For AWS specifically, you don’t need this pattern — and shouldn’t use it. GitHub Actions has native OIDC federation with AWS. The workflow assumes an IAM role directly. No credentials stored anywhere, not even in 1Password. That’s the correct approach for AWS.
The value of 1Password as a hub is precisely for the services AWS can’t federate with. That’s most of the SaaS layer your workflows touch.
The cleaner architecture: OIDC for AWS, 1Password service accounts for everything else — scoped per workflow, the same way ci-deploy is scoped to exactly the two credentials its job touches. “Everything else” describes which layer the vault covers. It’s not an instruction to put it all behind one grant.
What 1Password is actually building
Unified Access adds what service accounts don’t have: endpoint discovery (which AI tools and scripts are running on developer machines), credential scanning (finding exposed secrets in local files), and team-scale audit logs with attribution across multiple service accounts and vaults.
For a solo builder, those gaps don’t matter. The service account pattern covers the core use case.
For a team where ten engineers are running autonomous workflows against shared infrastructure — where you need to know which agent accessed which credential, who authorized it, and what it did — the enterprise layer is real. The accountability breakdown Unified Access describes is a genuine problem at scale.
The announcement is a signal, not a product you need. It confirms that the pattern is right. The credential hub model for autonomous workflows is where the market is going. The tooling to build it yourself already exists.
So what
If you’re running autonomous workflows — any CI job, any scheduled script, any agent that calls external services — the credential model matters. Not because of security theater, but because:
- You want to know what your agents accessed
- You want to rotate credentials without touching every workflow that uses them
- You want one place to cut access when something goes wrong
1Password service accounts give you that today, across every SaaS API that doesn’t have its own identity federation model. A scoped token per workflow. Exactly what that workflow needs in the vault behind it — not everything you own.
That’s infrastructure. Not a password manager.
This is the third post in an eight-post series on 1Password as infrastructure. The first covers what 1Password replaces in a builder setup. The second covers AI-native vault management. The fourth covers 1Password as the trust anchor in a live authentication chain — Auth0, MFA, autonomous agents, end-to-end. The fifth covers how the same pattern scales from solo builder to enterprise. The sixth covers op run — making any tool vault-transparent. The seventh puts this post’s scoping argument through its paces on a box that runs agents continuously instead of a CI job that exits. The eighth covers why scoped service accounts are still the floor, not the ceiling.