Identities for entities did.bot
agent llm did
Rust 94%
Astro 1%
Shell 1%
TypeScript <1%
JavaScript <1%
HCL <1%
Python <1%
CSS <1%
<1%
HTML <1%
Dockerfile <1%

README.md

didbot #

identities for entities

did.bot is an identity provider for AI agents and other machine entities.

Unlike classic IdPs, each identity is a fully featured ATproto account, backed by W3C Decentralized Identifiers (DIDs). This means that your AI agents (or cloud servers, or CI jobs, etc.) can immediately post on Bluesky, push code to Tangled, or do anything else possible on Atmosphere.

This project is pre-alpha, single-user, foolish, untested, unsafe, ill-advised, and largely AI generated to boot. No license or warranty is provided. There are no stability or data loss guarantees. Federation is not tested. Lexicons are not yet published. Abandon hope, all ye who enter.

Current release: v0.1.0

Features #

The didbot project aims to provide the following features:

  • Identity provisioning for agents and other machine entities in the form of a unique, stable, and globally visible ATproto account
  • Compatibility with a wide range of ATproto apps, from social media to file sharing
  • Publicly recorded attestations from human operators to agents and vice versa
  • Operator dashboard, including "E-Stop" capability to immediately pause agent tokens
  • Policies for limiting agent capabilities on the ATproto network, including:
    • Allow- or deny-list specific ATproto apps (OAuth clients)
    • Allow- or deny-list specific app permissions (OAuth scopes)
    • Immutable or banned record types (e.g., prevent agents from modifying their profiles, or writing posts)
  • Key and repository management for large numbers (>10k) of ephemeral ATproto accounts, without using public/ecosystem resources
  • Provide integrated DNS, TLS, and HTTP services for did:web
  • Provide ATproto labeler services for managed accounts
  • Maintain internal audit trails separate from repo contents

Being a good netizen #

The goal of didbot is to make the internet better for humans. Provisioning machine identities is just a tool to accomplish that goal.

However, there are many ways that providing credential access to agents can go wrong. Please ensure that your didbot deployment and usage respect the needs of all atproto users.

To that end, here is a non-exhaustive list of recommendations for a respectful didbot deployment:

  • Do not register any human accounts on a didbot PDS, ever. This presents a severe risk of permanent data loss, with no migration support whatsoever. It also undermines the effort put into community safety features like accurate agent attribution.

  • Do not attempt to mask your identity as a didbot operator, since this is how other people can reach you about abuse, loss of control, or other risks. Turning on DNS privacy is fine, obfuscating your own DID is not.

  • Do not use didbot-issued credentials to pursue unsolicited interactions with humans. This includes "term-search-and-reply" agents, issuing "drive-by" PRs against upstreams, or anything else that would cause someone's first interaction with didbot to be negative.

  • Do not allow open registration to your did.bot instance. Agent operators are expected to deploy and maintain their own instance to reduce blast zone, maintain attribution, and make reputation-based PDS interactions easier.

  • Do not operate did.bot if you don't understand how it works, or on behalf of someone else who doesn't. This project is intended for advanced users only.

  • Do not operate did.bot unless you can commit to maintaining your domain, DNS zones, records, and DID documents in perpetuity. Creating and then failing to resolve accounts can break data validation anywhere that your accounts interacted.

  • Do not block access to public bot.did.* endpoints such as listAgents. Agents must have public DID documents (even when only operating within private spaces), so they are are iterable via DNS enumeration anyways.

  • Do not consume atproto ecosystem resources. didbot accounts are cheap, but did:plc operations or Tangled vouches have side effects beyond your own PDS. Uncontrolled use of third-party resources will get your PDS rate-limited or defederated entirely.

  • Do not attempt to bypass apps that have opted out of supporting did.bot accounts (or bot accounts in general). If did.bot ships with a disabled policy for an app/scope/collection, this is for a good reason.

  • Do not override an account's declared AI preferences. An atproto account can publish a community.lexicon.preference.ai record saying how it wants AI systems to use its public data. A didbot deployment must not write records naming that account, or index its data, against what that record declares — deployment policy narrows what agents may do and never widens past somebody else's declaration. A deployment should also publish how to be left alone by all of its agents at once — an entity-scoped record naming the deployment's domain — rather than making somebody work it out. plan/ai-preference.md is where that check is being built.

  • Do not attempt to modify the did.bot source code to disable "community safety" features such as:

    • bot.did.operator check on startup
    • Bot flag on the BSky profile
    • bot.did.registration records
    • community.lexicon.preference.ai checks on writes and on indexing

Documentation #

  • plan/ — what is built and what is not, one file per capability, with the reasoning beside the work; plan/milestones.md reads the same work as releases
  • docs/web-surfaces.md — the four websites around this project and which is served by what
  • docs/trust-model.md — what the system can and cannot prove about an agent
  • docs/deployment.md — the zone, the hosts, and what a compromise of each reaches
  • docs/write-pipeline.md — what a write passes through before it reaches the log: the order, what each stage checks, and what it answers
  • docs/names.md — the records and documents behind one example account, and why an agent hostname costs no DNS record
  • cargo doc --workspace --no-deps --document-private-items — the narrative pages under docs/, compiled into the API documentation
  • site/ — the did.bot website: marketing pages, docs/ rendered as prose, and the API documentation above, mounted at /api/. scripts/build-site.sh builds all three; scripts/publish-site.sh builds and syncs to the bucket behind did.bot (dry-run by default — see site/README.md).

Checks #

Two things check this repository, and both are run by hand.

prek install wires the commit hooks. prek.toml is the list; without that one command none of it is installed and a commit is checked by nobody. The pre-commit stage runs file hygiene (merge markers, large files, YAML/TOML/JSON parsing, line endings, trailing whitespace) on every commit, and then, only when a commit touches the files each cares about:

  • cargo fmt --all on a .rs change; cargo clippy --workspace --all-targets --all-features -- -D warnings on a .rs, Cargo.toml or Cargo.lock change; and cargo doc --workspace --no-deps --all-features --document-private-items on those plus docs/*.md and .cargo/config.toml, since the prose pages are include_str!'d into the doc build. All three act on the whole workspace whatever they are handed, and .cargo/config.toml sets -D warnings for rustdoc too, so this is where the wait is — minutes, and longer against a cold target/. A commit touching only docs/*.md pays it. That is what a --no-verify commit gives up.
  • scripts/doc-lint.sh on docs/*.md, scripts/check-plan.py and scripts/gen-plan-readme.py --check on plan/*, bash -n on scripts/*.sh, and scripts/test-publish-site.sh on the publish scripts — that last one is a test run too, against a stubbed aws.
  • cargo test -p didbot-lexicon --all-features on a lexicons/*.json change. This is the only Rust test any hook runs.
  • scripts/build-site.sh on site/, docs/*.md or crates/didbot-site-anim/. It assumes site/node_modules already exists, and it ends by running site/tests — so a docs/*.md commit runs those too.

The commit-msg stage runs committed against committed.toml, so a subject that is not a Conventional Commit is rejected as it is written, and stamps a Change-Id trailer on a commit that lacks one.

scripts/ci.sh [<base>] is everything the hooks do plus the parts they cannot. It runs prek run --all-files, so a hook whose files pattern never matched the branch runs anyway; replays the commit-msg stage over every commit in <base>..HEAD, which catches messages written with the hook off (<base> defaults to $CI_BASE, then origin/main, and the stage is skipped with a note if neither resolves); and then runs cargo test --workspace --all-features. That last step is the only thing anywhere that runs the whole suite. Budget tens of minutes for a cold run.

There is no continuous integration. The repository carries no pipeline configuration, and nothing runs any of the above on a push or a pull request. A branch is checked when a person checks it.