Sync to LangGraph Platform
LangGraph Platform runs your Agent Server for you, which means there is no container to inject into: the deployment's secrets are its environment, and the control plane is the only way to set them. A binding owns one deployment's secrets.
| At a glance | |
|---|---|
| What seekrit writes | A deployment's secrets, delivered to the agent container as environment variables |
| Addressed by | The deployment UUID |
| Connection carries | The region (or a self-hosted control-plane URL), and a workspace ID for org-scoped keys |
| Token permission | A LangSmith API key that can update the deployment |
| Takes effect | On the new revision the write creates — a rebuild and rollout |
| Value visibility | Readable through the control plane by anyone with a key for the workspace |
New to sync? Read Third-party sync first — the decryption grant, name mapping, deletions, and failure handling are the same on every destination.
A push redeploys the agent. LangGraph Platform applies a secret change by creating a new revision, and its control plane offers no way to stage a value without shipping it. In-flight runs are interrupted.
seekrit keeps that to the minimum it can: it reads the deployment first and
sends nothing when nothing would change, so the periodic reconcile never
rolls your agent on its own. But a rotation does. If the agent runs somewhere
you control the process instead, seekrit run injects the
same values with no copy at the platform and no redeploy.
1. Create a LangSmith API key
In LangSmith, Settings → API keys → Create API key. Prefer a
workspace-scoped key (lsv2_pt_…): it names its own workspace, so the
connection needs nothing else. An organization-scoped key reaches every
workspace in the org, and without a workspace ID the control plane refuses it
with a bare 403.
printf '%s' "$LANGSMITH_API_KEY" \
| seekrit sync connect --name acme-langgraph --provider langgraph-platform
That is the whole connection for a US account. Two things can change it:
# An account in another region — chosen at signup and fixed afterwards.
printf '%s' "$LANGSMITH_API_KEY" \
| seekrit sync connect --name acme-langgraph --provider langgraph-platform \
--langgraph-region eu
# An organization-scoped key, which has to say which workspace.
printf '%s' "$LANGSMITH_API_KEY" \
| seekrit sync connect --name acme-langgraph --provider langgraph-platform \
--langgraph-tenant 8f1c2b3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d
The region matters more than it looks. LangChain runs the control plane on four
hosts, a key minted in one is not accepted by another, and the failure is a
plain 401 — so the wrong region here looks exactly like a bad credential:
--langgraph-region | Control-plane host |
|---|---|
us (default) | https://api.host.langchain.com |
eu | https://eu.api.host.langchain.com |
apac | https://apac.api.host.langchain.com |
aws-us | https://aws.api.host.langchain.com |
An account created at smith.langchain.com is us.
Self-hosted LangSmith. Pass --base-url instead of --langgraph-region,
pointing at the control plane on your own host — it is served under
/api-host, e.g. https://langsmith.acme.com/api-host. It must be https:,
because that address carries the API key. Setting both a region and a base URL
is refused rather than resolved in seekrit's favour.
2. Bind an environment
A deployment has one set of secrets, so the deployment is the whole destination — there is no per-revision or per-graph scope, and no equivalent of Vercel's production/preview split. A deployment that needs different values is a different binding.
seekrit sync verify acme-langgraph --provider langgraph-platform \
--langgraph-deployment 3970e0fe-8564-4903-9a55-c5f8de49fb8b
seekrit sync enable --connection acme-langgraph --provider langgraph-platform \
--langgraph-deployment 3970e0fe-8564-4903-9a55-c5f8de49fb8b \
--app storefront-agent --env production --acknowledge-decryption
--langgraph-deployment is the deployment UUID from its dashboard URL, or the
id from GET /v2/deployments; --app is the seekrit application the
environment belongs to.
Verify checks the deployment through its revision list rather than by fetching the deployment. Both prove the same three things you can get wrong from the connection dialog — key valid, workspace reachable, deployment real — but a revision carries only ids, timestamps, status and source, never a value. A deployment whose first revision is still building answers with an empty list, which passes: the deployment is there, and that is the question.
How a push behaves
- It reads before it writes. The array sent is the array the deployment ends
up with, so seekrit reads the current secrets and writes back
(existing − removed) ∪ seekrit. Sending only seekrit's names would delete every environment variable on the deployment that seekrit does not manage. - Values you set by hand survive. A
LOG_LEVELadded in the dashboard, or another team's key, is carried through a push exactly as it was read. - A run that would change nothing sends nothing. This is the one that matters here: without it, the reconcile timer would build a new revision of your agent every few minutes forever.
- Only
secretsis ever sent. APATCHcarryingsource_config,source_revision_configorrevision_sourcewould decide which code the new revision builds. Omitting them lets the control plane fall back to the deployment's own source, so a secrets push can never be the thing that ships new application code.secret_references— Kubernetes Secret references on self-hosted installs — is never sent either. - A rejected write is blamed on every name in it, which is honest here: the
control plane validates the array before applying it, so a rejected
PATCHleaves the deployment exactly as it was and nothing landed. - A value the control plane echoes back in an error is scrubbed before the reason is stored on the run row — including a foreign value the array carried through.
Name and value rules
LangGraph Platform will not accept every name seekrit will. It reserves
the names it sets itself — LANGSMITH_API_KEY, LANGCHAIN_PROJECT,
POSTGRES_URI, REDIS_URI, PATH, PORT and around thirty more. seekrit
skips a reserved name rather than sending it, and reports it as a failure
against that name alone, because the whole run is one request: one
unacceptable name would otherwise take the entire environment down with it.
Watch for it if you use a --prefix.
A secret with an empty value is failed the same way. The control plane drops one rather than storing it, so a sent empty does not come back on the next read — and seekrit's "nothing changed" check would never agree, which would rebuild your agent on every reconcile tick for as long as the binding existed. Failing the one name is the cheap end of that trade.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
401 on every name | The key was revoked — or the connection names the wrong region, which fails identically | Check the region against the table above, then re-create the connection |
403 | An organization-scoped key with no workspace ID, or a key without update permission | Add --langgraph-tenant, or use a workspace-scoped key that can update the deployment |
404 on the deployment | The deployment name in the ID slot, or the deployment was deleted | Use the UUID from the dashboard URL |
| One name failed, rest landed | The mapped name is reserved by LangGraph, or its value is empty | Rename it (or fix the prefix); seekrit refuses to send it rather than fail the run |
| Every name reported failed at once | The single PATCH was rejected | Nothing landed — the control plane validates before applying. Fix the cause and re-run |
| The agent redeploys on every sync | A value really is changing every run — an interpolated reference, or a rotation schedule | Check the run ledger for which name; a stable environment sends no request at all |
| A run fails with "refusing to write" | The control plane returned masked secret values, so writing them back would overwrite real ones | Please report it — the connector needs updating, and it fails loudly rather than destroying your environment |
See also
- Third-party sync — the shared model, naming and filtering, deletions
- Agent sandboxes — the other half of agent hosting, where you do control the process
- CLI reference — every
seekrit syncflag