This repository has no description
3

Configure Feed

Select the types of activity you want to include in your feed.

JavaScript 88.3%
HTML 11.7%
6 1 0

Clone this repository

https://tangled.org/disnetdev.com/at-intents https://tangled.org/did:plc:nwlolhoghrux5dpeuwvofqsr
git@tangled.org:disnetdev.com/at-intents git@tangled.org:did:plc:nwlolhoghrux5dpeuwvofqsr

For self-hosted knots, clone URLs may differ based on your setup.



README.md

AT Intents#

A standard, registry-free way for atproto apps to declare what they can do — so other apps (and agents) can discover those capabilities from a user's own repo and route to them. No central directory: an app you use leaves a small record behind, and that footprint is the discovery surface.

 THE USER'S REPO                                    THE APPS' REPOS
 (your discovery footprint)                         (capability authority)
┌────────────────────────────────────────┐         ┌──────────────────────────────────────┐
│ dev.at-intent.usage  "I use Skyreader" │ ──DID─► │ Skyreader   dev.at-intent.capability │
│ dev.at-intent.usage  "I use Sill"      │ ──DID─► │             × 4   (verb, subject, …) │
│                                        │         ├──────────────────────────────────────┤
│ left behind by each app you use —      │         │ Sill        dev.at-intent.capability │
│ no registry, no install step           │         │             × 1   (passive)          │
└────────────────────────────────────────┘         └──────────────────────────────────────┘

   │  a consumer (app or agent) walks the loop — no hardcoded app list
   ▼
┌─ 1 RESOLVE ──┬─ 2 DISCOVER ──┬─ 3 MATCH ────┬─ 4 AUTHORIZE ─┬─ 5 ACT ──────┐
│ usage→appDID │ appDID→capab. │ "who can     │ union of repo │ passive: —   │
│ read-only,   │ records       │  <verb> this │ scopes; new   │ repo:  write │
│ no auth      │ (cache by DID)│  <subject>?" │ auth if needed│ service: call│
└──────────────┴───────────────┴──────────────┴───────────────┴──────────────┘

Every capability is a (verb, subject, handler) triple plus a delivery method (passive / repo / service) that says how the action actually reaches the app. The same record doubles as an agent tool definition — discovered from the user's data at runtime, scoped by their existing grants.

Start here#

You are… Read
understanding the system docs/overview.md
an app that does things (save/subscribe/share/annotate) docs/producers.md
an app that discovers + routes (menus, "open with", agents) docs/consumers.md
an AI agent asked to author records for a repo docs/agent-guide.md
writing a capability record docs/capability-spec.md
watching the loop run live in a browser (OAuth + real PDS writes) demo/

Try it in 30 seconds#

# See the discovery loop run offline (no network, no auth):
node resolver/cli.mjs --demo
node resolver/cli.mjs --demo --feed https://blog.example/rss   # who can subscribe?

# Validate + preview a capability record without writing it (zero deps):
cd tools
node write-capability.mjs examples/subscribe.capability.json --dry-run --identifier myapp.com

See it run for real — the share-sheet demo#

The CLI above runs the loop offline against fixtures. The demo/ is the same loop in a browser, against a live network: a "Share with…" share sheet that discovers the handlers already in your repo footprint and runs an action for real.

cd demo
npm install
npm run dev        # builds the bundle, then serves → http://127.0.0.1:8787/demo/

It walks the full pitch end to end:

  1. Discover (read-only, no login) — scan your repo for dev.at-intent.usage, resolve each app's dev.at-intent.capability records into one action graph.
  2. Match — keep the actions whose subject accepts the current page (a bare uri); the rest are shown greyed, with the subject they'd need.
  3. Consent — compute the minimal granular OAuth scopes those handlers declare (repo:… / rpc:…, never blanket write) and request exactly that set.
  4. Act — run an action live: repo writes a record into your PDS, service proxies an XRPC call through it, open navigates. Discovery is the upstream resolveActionGraph from resolver/, unchanged.

Because the scopes are granular, discovery has to run first to know what to ask for — which is exactly why "ask for what the repo says is needed, and nothing more" is the whole point. See demo/README.md for the auth model (loopback vs hosted), the code map, and the @atproto/api service-call wrinkles.

What's in this repo#

lexicons/    dev.at-intent.capability + dev.at-intent.usage (the two records)
tools/       write capability/usage records — from a JSON file or interactively
resolver/    the consumer-side discovery loop (lib + CLI + offline fixtures)
demo/        share-sheet browser consumer — discovery + OAuth + live PDS actions
docs/        overview, producer/consumer guides, agent guide, spec reference

Status#

Exploration / draft. The namespace dev.at-intent.* is a working placeholder (likely long-term home: community.lexicon.*); it's defined in one constant (tools/lib/nsid.mjs) plus the lexicon id fields, so re-homing is mechanical. No app publishes these records on the live network at scale yet — the resolver fixtures stand in for that on the CLI — but the demo/ already runs the whole loop against a real repo footprint over live OAuth, so the end-to-end path (discover → consent → act) works today, not just in fixtures.

Prior art & context#

Descends from Web / Android / Apple App Intents — but replaces their handler registry with the user's repo footprint, which is what W3C Web Intents (~2012) lacked. Builds on atproto OAuth permission sets (proposal 0011), lexicon resolution, and lexicon embeds. See docs/overview.md for the full picture.