docs / agent-id / getting started

Getting started

Install

Python — package fg-agent-id, import path fg_agent_id (renamed from fareground-agent-id). Requires Python ≥ 3.11; the only runtime dependency is cryptography>=42.0:

pip install fg-agent-id
pip install "fg-agent-id[redis]"   # optional: RedisChallengeStore (redis>=4.0)

TypeScript — package @fg/agent-id. Requires Node ≥ 20, zero runtime dependencies (all crypto via WebCrypto crypto.subtle), ESM-only:

npm install @fg/agent-id

Working from source: pytest runs the Python suite; from js/, npm test builds and runs the TS suite, and npm run conformance checks the golden vectors alone. python spec/generate_vectors.py regenerates spec/vectors.json.

First identity in five minutes

An owner (cold key) authorizes an agent (hot key), the agent publishes a signed card, and anyone verifies both — with no registry in sight.

from fg_agent_id import AgentIdentity, OwnerIdentity

# 1. A cold owner key — this is the root of authority
owner = OwnerIdentity.generate("acme-corp")

# 2. Mint an agent: fresh keys + a signed delegation from the owner
agent = owner.create_agent("acme-buyer", scopes={"converse", "negotiate"})

# 3. Publish a signed self-description
card = agent.card(endpoints={"http": "https://buyer.example/inbox"})
card.verify()                       # self-verifying: no registry, no network

print(agent.address)                # amp:key:<base58>
print(card.did)                     # did:amp:<base58>

# 4. Anyone can verify what the agent is allowed to do
scopes = agent.delegation_chain.verify(agent.address)
assert scopes == frozenset({"converse", "negotiate"})

What just happened

TypeScript quickstart

Same wire format, async crypto, camelCase names, options-object constructors. Note the public-key accessor is keys.public_ (trailing underscore):

import {
  KeyPair, addressFromSigningKey, AgentCard,
  Delegation, DelegationChain, ChallengeStore,
} from "@fg/agent-id";

const keys = await KeyPair.generate();
const address = addressFromSigningKey(keys.public_.signing);

const card = await AgentCard.create({ keys, address, name: "my-agent" });
await card.verify();

const grant = await Delegation.grant({
  issuerKeys: keys, issuerAddress: address,
  subjectAddress: worker, scopes: ["read"], ttlSeconds: 3600,
});
const scopes = await new DelegationChain([grant]).verify(worker);

The TS twin exposes the primitives (KeyPair, AgentCard, Delegation, …) directly — the Python AgentIdentity/OwnerIdentity convenience wrappers are not ported. Compose the pieces yourself; the wire bytes are identical either way.

Where to go next