AgentKey SDK
AgentKey is an authorization and evidence layer for AI agents. Before an agent takes an action, the SDK asks the AgentKey API whether it is allowed, denied, or requires human approval. Both the decision and what the agent actually did are recorded as hash-chained evidence events you can inspect in a dashboard.
Installation
Python (3.8+, zero dependencies):
pip install agentkey
JavaScript / TypeScript (Node 18+, zero dependencies, ESM):
npm install agentkey-ai
Next steps after install
pip wheels run no code on install, so pip cannot print guidance for you. npm is different, and this section states its behavior precisely rather than assuming it: dependency install scripts still run by default on npm 11 and earlier; npm 11.16.0 and later print a warning whenever an install executes them; and npm 12 no longer executes preinstall, install, or postinstall scripts from dependencies "unless they are explicitly allowed in your project" (GitHub changelog, June 2026), with npm approve-scripts as the approval path. A postinstall banner in this package is therefore technically possible on npm 11 and earlier, but we do not ship one: it would be suppressed or gated on current npm, and a security tool should not run code at install time. The immediate next step:
agentkey init # paste your API key (masked) and validate it against production
agentkey doctor # verify the full setup: SDK, credentials, API, key validity
After npm install agentkey-ai, invoke the same commands with npx: npx agentkey init, npx agentkey doctor.
The CLI never prints your key. agentkey init saves a pasted key to a local config file (~/.agentkey/config, or %APPDATA%\agentkey\config on Windows; permissions 0600, the only file the key is ever written to). The AGENTKEY_API_KEY environment variable overrides it, and agentkey logout deletes it. See "Developer CLI" below.
Get an API key
- Sign up at the AgentKey dashboard: https://agentkey.us
- Open the Connect wizard (or Agents, then create an agent).
- Generate an API key. It is shown once. Run
agentkey initto save it to the local config file, or export it asAGENTKEY_API_KEY. Never hard-code it.
First authorization (guided)
Run this right after agentkey init (or with AGENTKEY_API_KEY exported). It performs ONE real, least-privilege authorization: sandbox.send_test, an isolated test capability every new agent ships with. It can only ever return allow or deny; it never performs a real external side effect, never touches a real tool, and grants nothing beyond that single permission. The decision is made by the real policy engine and recorded as hash-chained evidence.
Python:
from agentkey import AgentKeyClient
ak = AgentKeyClient() # reads AGENTKEY_API_KEY, or the config file from `agentkey init`
result = ak.check_permission(action="send_test", resource="sandbox")
print("session_id: ", result.get("session_id"))
decision = "ALLOW" if result.get("allowed") else ("APPROVAL REQUIRED" if result.get("approval_required") else "DENY")
print("decision: ", decision, "-", result.get("reason"))
if result.get("event_id"):
print("evidence_event_id:", result["event_id"])
print()
print("YOU'RE DONE - your first real authorization was decided by the policy")
print("engine and recorded as verifiable evidence. See it in the dashboard:")
print("https://agentkey.us/sessions/" + str(result.get("session_id")))
else:
reason = str(result.get("reason") or "")
if "Invalid API key" in reason:
print("Your key is invalid - create one at https://agentkey.us/connect")
elif "No permission configured" in reason:
print("This agent has no sandbox.send_test permission yet. Add one in the")
print("dashboard (Agents -> Permissions): resource 'sandbox', action")
print("'send_test', decision allow - then run this again.")
else:
print("Denied by policy:", reason)
JavaScript / TypeScript (save as first-authorization.mjs, run with node first-authorization.mjs):
import { AgentKeyClient } from "agentkey-ai";
const ak = new AgentKeyClient(); // reads AGENTKEY_API_KEY, or the config file from `npx agentkey init`
const result = await ak.checkPermission({ action: "send_test", resource: "sandbox" });
console.log("session_id: ", result.session_id);
const decision = result.allowed ? "ALLOW" : (result.approval_required ? "APPROVAL REQUIRED" : "DENY");
console.log("decision: ", decision, "-", result.reason);
if (result.event_id) {
console.log("evidence_event_id:", result.event_id);
console.log();
console.log("YOU'RE DONE - your first real authorization was decided by the policy");
console.log("engine and recorded as verifiable evidence. See it in the dashboard:");
console.log("https://agentkey.us/sessions/" + result.session_id);
} else {
const reason = String(result.reason || "");
if (reason.includes("Invalid API key")) {
console.log("Your key is invalid - create one at https://agentkey.us/connect");
} else if (reason.includes("No permission configured")) {
console.log("This agent has no sandbox.send_test permission yet. Add one in the");
console.log("dashboard (Agents -> Permissions): resource 'sandbox', action");
console.log("'send_test', decision allow - then run this again.");
} else {
console.log("Denied by policy:", reason);
}
}
A wrong, expired, or revoked key fails closed exactly like any other call (allowed: false); the scripts above tell you which case you are in.
Decisions: allow, deny, ask
check_permission / checkPermission evaluates the permissions you configured for the agent:
- allow:
allowed: true. Run the action, then record the execution (below). - deny:
allowed: falsewith the server's reason. Do not run the action. - ask (human approval):
allowed: false,approval_required: true. The request appears on the Approvals page in the dashboard, where a human approves or denies it. Do not run the action until it is approved.
Fail-closed: if the service cannot return a valid decision within 5 seconds, the SDK returns:
{ "allowed": false, "reason": "agentkey_unreachable", "fail_closed": true }
Treat fail_closed: true as an infrastructure failure and allowed: false without it as an authorization decision. Either way the agent must not proceed.
wrap(): authorize every tool call in one line
agent = ak.wrap(my_agent) # observe (default): records, blocks nothing
agent = ak.wrap(my_agent, mode="enforce") # raises AgentKeyDenied on a denial
const agent = ak.wrap(myAgent); // observe (default)
const agent = ak.wrap(myAgent, { mode: "enforce" }); // raises AgentKeyDenied on a denial
wrap() detects an MCP client (callTool / call_tool), a LangChain agent or tool list, a plain object or dict of functions, or a single function. Observe mode records every call and blocks nothing, so you can see what AgentKey would have caught before trusting it with enforcement. Enforce mode raises AgentKeyDenied and does not run the tool. If no session id is passed, a session is started automatically and ended best-effort at process exit.
Sessions
Every decision and execution is recorded as an evidence event on the session's hash chain. Group a task into one session:
s = ak.start_session()
# ... checks and actions ...
ak.end_session(s["session_id"])
const s = await ak.startSession();
// ... checks and actions ...
await ak.endSession({ sessionId: s.session_id });
Recording what the agent actually did
After an allowed action runs, record the execution, linked back to its decision by authorization_id:
auth = ak.check_permission(action="send_email", resource="gmail", session_id=sid)
if auth["allowed"]:
send_email(...)
ak.record_action(session_id=sid, authorization_id=auth["event_id"], tool="gmail",
action="send_email", resource="gmail", result_status="success")
record_action never refuses to record, so evidence is not lost for billing reasons. Actions that run without any authorization decision are surfaced on the dashboard as findings (executions_without_authorization), because the SDK is self-reported: an agent that bypasses the wrapped functions produces no evidence.
guard(): authorize, run, record in one call
out = ak.guard(sid, "gmail", "send_email", lambda: send_email(...), arguments={"to": "x@company.com"})
const out = await ak.guard({ sessionId: sid, resource: "gmail", action: "send_email" }, async () => sendEmail());
If authorize denies, guard returns the denial and does not run the function.
Delegated authorization
A parent agent can delegate a scoped subset of its permissions to a child agent. Scopes are resource:action strings, must be a subset of the parent's own permissions, and chains are depth-limited. See delegate() in the source docstrings.
Developer CLI
Both packages ship the same commands (init, doctor, logout). They validate your setup against the production API and never change SDK authorization behavior. Every CLI network call has an explicit 10 second timeout, so a wrong URL, an offline machine, or firewalled egress fails closed with a next step instead of hanging.
The API key is resolved, highest first, from: an explicit constructor argument (SDK), the AGENTKEY_API_KEY environment variable, then the config file (~/.agentkey/config, or %APPDATA%\agentkey\config on Windows). The environment variable always wins, so CI and anyone already exporting it are unaffected.
agentkey init validates the configured key against the production API. With no key configured it prompts with masked input, validates the pasted key, and saves it to the config file (created with permissions 0600 inside a 0700 directory) so later commands and SDK clients resolve it automatically. The key is never printed or logged, and that file is the only place it is ever written.
agentkey doctor runs a fast end-to-end check: SDK installed, credentials configured (reporting whether the key came from the environment or the config file), API reachable, credentials valid, authorization endpoint reachable. When the API is unreachable the network-dependent checks are skipped and reported as such. Each failed check states the practical next step. No stack traces.
agentkey logout deletes the saved config file. The environment variable, if set, is untouched (the CLI cannot unset your shell).
A successful init or doctor means the developer is authenticated and configured. It never means the agent's actions are automatically allowed; authorization decisions remain fail-closed exactly as before.
Production API
Base URL: https://agentkey.us (the SDK default). Override it with base_url (Python) or baseUrl (JavaScript) if you self-host.
All endpoints are POST with a Bearer API key, under /api/functions/:
authorizerecord_actionstart_sessionend_sessiondelegatevalidate_api_key(GET)
Raw HTTP:
curl -X POST https://agentkey.us/api/functions/authorize \
-H "Authorization: Bearer agent_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{"action":"send_email","resource":"gmail","arguments":{"to":"x@company.com"}}'
Dashboard
Sessions, evidence events, approvals, findings and permission settings: https://agentkey.us
Troubleshooting
- "Request blocked by edge WAF (Cloudflare error 1010). This is not an authentication failure." The production API sits behind a WAF that blocks some client signatures. The SDK sends an identifying User-Agent on every request (
agentkey-sdk-js/<version>in the JavaScript SDK,agentkey-python-sdkin the Python SDK). If you see this error, something between your code and the API (a proxy, a modified SDK, or a non-SDK integration) is stripping or replacing that header. Restore it, then retry. This error never means a bad key. - Both SDKs detect the Cloudflare 1010 HTML page and raise the explicit error above; it never surfaces as a generic parse error, an unreachable API, or an authentication failure.
Security limitations (current, accurate)
- Evidence events are hash-chained per session, and session Merkle roots are attested with HMAC-SHA256 under a server-side key. This detects altered or missing events in stored evidence. It is not an asymmetric digital signature scheme, it does not make records forgery-proof against a compromised server, and it is not a non-repudiation guarantee.
- SDK instrumentation is self-reported.
wrap()andrecord_actionrecord what the agent reports; an agent that calls tools outside the SDK produces no evidence. This is reported as anexecutions_without_authorizationfinding, but not prevented. - Checks fail closed on network errors and timeouts. In observe mode the SDK still lets the call run; only enforce mode blocks it.
- No SOC 2 or other third-party compliance audit has been completed.
License: MIT.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file agentkey-1.2.0.tar.gz.
File metadata
- Download URL: agentkey-1.2.0.tar.gz
- Upload date:
- Size: 16.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
node
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c93486ddea84305b2e234933d5f7bb3ae9ec0122805aa2bb94075afcbfbbd264
|
|
| MD5 |
f61cd0b415e0e1a88f6b641782d05294
|
|
| BLAKE2b-256 |
1d7986dbd9cbb37e372c001d5cd590b34f6f507bcc2da9dbcefd0f713566a05a
|