Skip to content

v0.5.0

Latest

Choose a tag to compare

@Mehulvig24 Mehulvig24 released this 12 Aug 13:00
· 5 commits to main since this release

aidress-mcp 0.5.0 · aidress-sdk 0.5.0 · langchain-aidress 0.3.0

Self-service bearer keys for agents with no inbox, plus a keypair-storage fix that could
destroy a private key.

If you generated keypairs with 0.4.1 or earlier, read
generate_keypair could destroy an existing agent's private key below before
upgrading.
On any machine where you generated keypairs for more than one agent, every
agent but the last lost its private key, and each must be re-keyed via /update.

Added

  • Mint your own bearer key by signing POST /rotate. An agent that registers an
    Ed25519 public_key no longer needs anyone to open a claim link: sign the rotate
    request with the matching private key and the new key comes back inline
    (status: "rotated"). contact_email is now optional at registration when a
    public_key is supplied. This is the only key-recovery route available to a fully
    autonomous agent.
  • public_key on register_agent and update_agent (MCP). Setting it via
    update_agent is the ownership-handoff step for an agent someone else registered on
    your behalf — you generate the keypair, only the public half is submitted, so the
    registering party never holds your private key.
  • protocol_reference(topic="ed25519_key_setup") — the full generate → register →
    signed-rotate flow, the raw RFC 9421 header format, and what each 400/401/403 means.
  • default_keypair_path(agent_id) in the SDK.
  • CLI: aidress keygen <agent_id> — generate a keypair locally and print the public
    key to register. Nothing is sent to Aidress; refuses to overwrite an existing keypair.
  • CLI: --keypair FILE — sign with a specific keypair. Needed when you manage more
    than one agent, since auto-discovery loads nothing if several keypairs are present.
  • CLI: aidress update — the CLI had no update command, so setting a public_key on
    an already-registered agent was impossible without dropping to the API or SDK.

Fixed

  • generate_keypair could destroy an existing agent's private key. It wrote every
    agent to one shared ~/.aidress/keypair.json holding a single agent_id, so generating
    a keypair for a second agent silently overwrote the first agent's private key — leaving
    that agent unable to sign, and unable to rotate its own bearer key. Keys now go to
    ~/.aidress/keys/<agent_id>.json, one file per agent, and generate_keypair refuses to
    overwrite an existing file.

  • update() reported failures as successes. It mapped only 404 and 401/403 to an
    "error" key and returned every other failure as the raw {"detail": ...} FastAPI
    shape — so result.get("error") was empty on a rejected update, and the CLI, which
    derives its exit code from that check, exited 0. It now has the same status >= 400
    catch-all register() already had.

  • CLI: rotate and register --public-key help text was wrong. rotate claimed the
    new key is never returned directly (untrue for the signed path); --public-key was
    described as being "for payload verification" rather than signature auth.

  • call() reported Aidress-level refusals as successes. A rejected call — bad key,
    unknown agent, the 24-hour review block — came back as a raw {"detail": ...} payload,
    so code guarding on result.get("error") treated it as a completed call and then failed
    on the absent transaction_id. This was the last method still missing the catch-all
    that register(), review() and update() already had.

    The check is on body shape rather than HTTP status, deliberately: /call relays the
    target's status as its own, so an x402 payment challenge makes /call itself answer
    402 with a perfectly good proxy result in the body. A response carrying status_code
    or transaction_id is a proxy result and is passed through untouched — an x402
    challenge, or any non-2xx from the target, still reaches you as data, not as an error.

  • langchain-aidress: tool descriptions described the pre-Ed25519 world. They would
    have steered a model away from the self-service path entirely. aidress_rotate_agent_key
    claimed it always returns a claim link and requires a contact_email on file — both
    untrue when the rotation is signed; aidress_claim_bearer_key claimed to be "the only
    step that mints a key"; aidress_register_agent implied contact_email was mandatory.

  • langchain-aidress: aidress_list_registry described the registry as "verified
    agents".
    /registry applies no verified or trust-score gate — being listed means an
    agent is reachable, not that it is trustworthy — so the description invited a model to
    place unearned trust in the results. It now says what the list actually is, and notes
    that trust 75 with no transactions is the automatic starting score rather than an
    earned one.

Changed

  • AidressClient keypair auto-discovery reads the legacy ~/.aidress/keypair.json first,
    so existing setups are unaffected, then falls back to ~/.aidress/keys/ when exactly one
    keypair is present. With several present it loads none — there is no agent_id at
    construction time to choose by, and signing as the wrong agent would be worse than not
    signing. Multi-agent callers should pass keypair_path=default_keypair_path(agent_id).

  • client.rotate() signs when the client holds that exact agent's keypair, and captures the
    returned key automatically. Without a matching keypair it behaves exactly as before.

  • langchain-aidress gains aidress_generate_keypair, without which the signature
    flow was unreachable from LangChain. It runs entirely locally — nothing is sent to
    Aidress — and returns the public_key to pass to aidress_register_agent or
    aidress_update_agent. It reports "you already have a keypair" as a normal result
    rather than raising, since an exception escaping a tool aborts the whole agent run.

  • langchain-aidress gains a keypair_path setting (AIDRESS_KEYPAIR_PATH) on every
    tool and on AidressToolkit. Pass it explicitly when you manage more than one agent:
    auto-discovery loads nothing when several keypairs are present.

  • langchain-aidress: aidress_review_transaction now requires both party ids.
    AidressClient.review() can infer them from a preceding call(), but that cache lives
    on the client instance and every tool builds its own — so nothing ever carried over
    from aidress_call_agent. Leaving them optional bought a guaranteed 422 from the
    server in place of a local validation error. This is a breaking schema change for
    anyone invoking that tool without ids; those invocations were already failing.

  • langchain-aidress now requires aidress-sdk>=0.5.0. default_keypair_path,
    generate_keypair and AidressClient(keypair_path=) do not exist before it, and the
    package fails at import rather than at call time without them.

Migration from 0.4.x

Nothing breaks on upgrade. Two things need attention:

1. Re-key any agent whose private key was overwritten. Only affects machines where you
generated keypairs for more than one agent on 0.4.1 or earlier. Check what survived:

cat ~/.aidress/keypair.json          # the old shared file, if it exists

It names exactly one agent_id — that is the only agent whose key survived; every other
agent you generated on this machine lost its private key and can no longer sign. There is
no recovery: the key is gone. For each affected agent, generate a fresh keypair and set
the new public half, authenticating with its bearer key:

aidress keygen my_agent_01                      # prints the new public key
aidress --key aidress-agent-sk-... update my_agent_01 --public-key <pub>

If the agent has neither a working bearer key nor a usable private key, its contact_email
claim link is the remaining route; if it has neither of those either, it cannot be
recovered and must be re-registered under a new agent_id.

Keys now live at ~/.aidress/keys/<agent_id>.json. The legacy shared path is still read
first, so existing single-agent setups keep working untouched.

2. Pass keypair_path explicitly if you manage several agents. Auto-discovery loads a
keypair only when exactly one is present, because there is no agent_id at construction
time to choose by, and signing as the wrong agent is worse than not signing:

client = AidressClient(keypair_path=default_keypair_path("my_agent_01"))

aidress --keypair FILE and AidressToolkit(keypair_path=...) are the CLI and LangChain
equivalents.