Getting started (developer first-contact)
This doc is for developers who want to run agent-locksmith standalone — no Docker bundle, no site repo, just the Rust crate and the daemon. Useful for evaluation, embedding in your own deployment system, or exercising the codebase.
For the production Layer8 Proxy bundle deployment story, see the Layer8 Proxy deploy guide.
Prerequisites
- Rust toolchain (1.85+ — agent-locksmith uses edition 2024).
- A C toolchain (cargo + libssl-dev / openssl).
- Optional:
jq,curl.
Step 1: Build
git clone git@github.com:SentientSwarm/agent-locksmith.git
cd agent-locksmith
cargo build --release
Two binaries land in target/release/:
locksmithd— the daemon. Reads--config <path>, binds the agent listener + admin UDS, runs.locksmith— the operator + agent self-service CLI. Talks to a running daemon via the admin UDS (default) or admin HTTPS.
Step 2: Mint an operator credential
The operator credential is what proves you're the operator when calling admin endpoints (registering agents, putting tool entries, querying audit, etc.).
./target/release/locksmith bootstrap-operator --name dev > operators.yaml
Output goes to two streams:
- stdout —
operators.yamlcontent (one operator entry, with the secret argon2-hashed). Pipe to a file. - stderr — the cleartext wire token, printed ONCE. Save it now; the daemon validates against the hash, never the cleartext.
Sample stderr:
✓ Operator credential minted.
Wire token (save this NOW — cannot be recovered):
lkop_JJzZehsZbxC41cYZoPFrlg.DkhOj8p7mNbyIOd7xErWBDKSgE3zEnCPPVNMdDbDOn0
Install on the operator's host:
export LOCKSMITH_OP_TOKEN='lkop_JJzZehsZbxC41cYZoPFrlg.DkhOj8p7mNbyIOd7xErWBDKSgE3zEnCPPVNMdDbDOn0'
bootstrap-operator is offline — it doesn't talk to a daemon. Re-running it
mints a fresh token; the prior wire token stops working as soon as you replace
operators.yaml.
Step 3: Configure the daemon
config.example.yaml in the repo is a working minimal config. Copy it and
adjust operator_credentials_path to point at your operators.yaml from
step 2:
cp config.example.yaml config.yaml
Edit config.yaml so it has at least:
listen:
host: "127.0.0.1"
port: 9200
auth_mode: bearer
admin_socket:
path: "/tmp/locksmith.sock"
operator_credentials_path: "./operators.yaml"
database:
path: "./locksmith.db"
audit:
retention_days: 90
sweep_interval_seconds: 3600
Step 4: Start the daemon
./target/release/locksmithd --config config.yaml
You should see structured-JSON logs on stdout. Leave it running; open a new terminal for the next steps.
# In another terminal:
curl -sS http://127.0.0.1:9200/livez
# {"status":"live","uptime_seconds":N}
curl -sS http://127.0.0.1:9200/version
# {"name":"agent-locksmith","version":"2.7.1"}
Step 5: Register an agent
export LOCKSMITH_OP_TOKEN="lkop_..." # from step 2
./target/release/locksmith --socket /tmp/locksmith.sock \
agent register --name dev-agent --allowlist anthropic
The CLI prints the agent's bearer token:
public_id: yN2vR6jFKNYfIwNjFU2MSA
token: lk_yN2vR6jFKNYfIwNjFU2MSA.1TJlTmOgmswZYZx_aQHyjaNiugeJjudytNPFJgT9aqM
allowlist: ["anthropic"]
Save the bearer for step 6.
Step 6: Make a call
The seed catalog at /etc/locksmith/seed/catalog.yaml has 16 default
providers. Standalone runs pick that path up automatically if present; for a
dev box without it, point at the in-repo seed/catalog.yaml:
LOCKSMITH_SEED_PATH="$PWD/seed/catalog.yaml" \
./target/release/locksmithd --config config.yaml &
Then call Anthropic (set ANTHROPIC_API_KEY in the daemon's env first):
AGENT_TOKEN="lk_yN2v..."
curl -sS -H "Authorization: Bearer $AGENT_TOKEN" http://127.0.0.1:9200/models
# {"models":[{"name":"anthropic","path":"/api/anthropic","type":"api", ...}]}
curl -sS -X POST http://127.0.0.1:9200/api/anthropic/v1/messages \
-H "Authorization: Bearer $AGENT_TOKEN" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"model":"claude-haiku-4-5","max_tokens":40,"messages":[{"role":"user","content":"hi"}]}'
If you see a real Anthropic completion, the standalone setup is working.
What you've actually exercised
The standalone flow above hits all the current invariants:
- Per-agent bearer + ACL: the agent's
--allowlist anthropicmeans it can only reach/api/anthropic/.... Try/api/openai/...with the same bearer — you'll get 403tool_not_allowed. - Catalog substrate:
/modelsreturns kind=model only, ACL-filtered./toolsreturns kind=tool only. - Credential injection: locksmith reads
ANTHROPIC_API_KEYfrom its environment at startup and injectsx-api-key: <real-key>on the wire to Anthropic. Your agent never saw the real key. - Audit: every request gets one row.
What you DON'T get standalone
- pipelock egress chokepoint — locksmith goes direct to upstream; no DLP, no allowlist enforcement at the network layer. Production deploys add pipelock via the Layer8 Proxy compose bundle.
- lf-scan prompt/code scanner — same; opt-in middleware, not bundled standalone.
- Sealed-creds at rest — your
operators.yamland.envare cleartext on disk. The Layer8 Proxy sealed-cred mechanism is layered on top in the bundle. - Backup automation — the locksmith DB is just a SQLite file; back up
locksmith.db*like any other application state.
What's next
- CLI reference — every subcommand and flag.
- Architecture — user-level view of the daemon's runtime composition.
- Layer8 Proxy — the production Docker Compose bundle with pipelock + lf-scan + sealed-creds infrastructure.