You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Stop surfacing source: 'discovered' agents in the AAO public registry. The registry should reflect attested, opt-in agents only. Crawled-from-adagents.json agents that have not enrolled are not attested by their owner and should not be displayed, filtered on, or returned by the public API.
Why now
We have spent the last month patching the seams of registered-vs-discovered conflation:
Every one of these is a tax on a feature that no member asked for. Discovered agents are a crawler artifact, not a product. The registry's contract with members is "you enrolled, you are listed." A crawler-only entry breaks that contract from both sides — the listed agent never opted in, and the registry consumer can't tell what the entry means without reading three doc pages.
Scope of removal
Public API
/api/registry/agents — return only registered agents. Drop source, discovered_from, endorsed_by_publisher_member from FederatedAgentWithDetails.
/api/registry/agents/:url — 404 for URLs that only exist via discovery.
?source= query param — remove (introduced for Problem 3 step 2).
Same treatment for FederatedPublisher — registered publishers only.
Schema / types
server/src/schemas/registry.ts:432-484 — drop the ["registered", "discovered"] enum, DiscoveredFromSchema, EndorsedByPublisherMemberSchema.
server/src/db/federated-index-db.ts:378-505 — drop upsertDiscoveredAgent, getDiscoveredAgents, related update/expire helpers.
Crawler
server/src/crawler.ts — keep adagents.json parsing for the publisher-authorization graph (we still need to know who endorses whom for list_authorized_properties validation), but stop registering unknown agents from those listings. The crawler becomes a verification tool for known agents, not a discovery tool for new ones.
stats.discovered_agents (line 472) — remove.
Database
discovered_agents table — drop.
discovered_publishers table — drop, or preserve as crawled_publishers if any publisher-graph code still needs the row (decide during impl).
agent_publisher_authorizations — keep the table (authorizations still matter), but the source: 'agent_claim' | 'adagents_json' enum stays meaningful only as an audit field, not as a registry-source signal.
New migration to drop tables + clean up indices + remove cleanup/expiry jobs from migrations 331, 349, 432, 455, 461.
UI
server/public/agents.html — remove any source badge/filter/segment.
/registry page — single list, no tabs.
Docs
docs/registry/registering-an-agent.mdx — collapse the "four crawl paths" framing to "one path: enroll on your member profile."
docs/registry/index.mdx overview — drop the registered-vs-discovered explainer.
Remove endorsed_by_publisher_member and discovered_from references throughout.
Mintlify example responses — simpler, no per-source overrides.
Tests
Delete: server/tests/unit/registry-discovered-endorsement.test.ts, the discovered branches of registry-sync tests.
Update: any test asserting on source or merged-list behavior.
What we lose, and why it's fine
Visibility into "agents that exist in the wild but haven't joined." Real, but the registry was never the right surface for this. If we want a market-coverage view, build it as an internal ops tool, not a public registry tab.
Crawler-driven onboarding funnel. A discovered listing was an implicit nudge to the agent owner to enroll. We can replace this with an outbound email when the crawler sees a new adagents.json entry pointing at an unregistered URL — a stronger nudge than "you're already in the registry, ish."
Backwards compatibility for any external consumer that filtered on ?source=discovered. The ?source= param is days old; risk is near zero.
Migration plan
PR 1 — feature flag the public surface. Add REGISTRY_HIDE_DISCOVERED=true (default true in prod) that filters discovered out of /api/registry/agents + UI. No schema or DB changes. Ship behind flag, validate.
PR 2 — remove the type fields. Drop source / discovered_from / endorsed_by_publisher_member from response schemas and TS types. Update OpenAPI / docs.
PR 3 — service + DB cleanup. Strip federated-index.ts merge logic. Drop discovered_agents / discovered_publishers tables in a migration. Repoint crawler to verification-only mode.
Do we keep agent_publisher_authorizations populated from crawl? Probably yes — list_authorized_properties validation still depends on it. The change is "we record the relationship; we do not turn the relationship into a registry entry."
Outbound nudge? Worth it as a follow-up issue, not a blocker on this one.
Registry: remove
discoveredagents entirely — registered-only public surfaceRefs #3538 (Problem 3, Problem 6), #3547, #3573, #3495.
Proposal
Stop surfacing
source: 'discovered'agents in the AAO public registry. The registry should reflect attested, opt-in agents only. Crawled-from-adagents.jsonagents that have not enrolled are not attested by their owner and should not be displayed, filtered on, or returned by the public API.Why now
We have spent the last month patching the seams of registered-vs-discovered conflation:
/api/registry/agents. Public UI does not segment them. Shipped:?source=query param, schema annotations, doc copy.member: nulleven when the publisher domain is owned by an AAO member. Solution shipped: a newendorsed_by_publisher_memberfield. Net effect: more schema, more docs, more UI, to communicate a partial trust signal.adagents.jsonwere registered astype: 'buying'. The discovered path is the original source of the type-inference mess that fix(registry): flip type==='buying' filter inversions to 'sales' + add sales to by_type tally #3540/ops(registry): backfill stale member_profiles.agents types + crawler reclassify-on-disagreement #3541 just finished cleaning up.Every one of these is a tax on a feature that no member asked for. Discovered agents are a crawler artifact, not a product. The registry's contract with members is "you enrolled, you are listed." A crawler-only entry breaks that contract from both sides — the listed agent never opted in, and the registry consumer can't tell what the entry means without reading three doc pages.
Scope of removal
Public API
/api/registry/agents— return only registered agents. Dropsource,discovered_from,endorsed_by_publisher_memberfromFederatedAgentWithDetails./api/registry/agents/:url— 404 for URLs that only exist via discovery.?source=query param — remove (introduced for Problem 3 step 2).FederatedPublisher— registered publishers only.Schema / types
server/src/schemas/registry.ts:432-484— drop the["registered", "discovered"]enum,DiscoveredFromSchema,EndorsedByPublisherMemberSchema.server/src/types.ts:1061-1108—FederatedAgent.source,discovered_from,endorsed_by_publisher_member;FederatedPublisher.source,discovered_from.Service layer
server/src/federated-index.ts:30-140—listAllAgents()no longer merges; returns registered only. Delete the dedup-by-canonical-URL logic that fix(registry): canonicalize agent_url before registered/discovered collapse (trailing slash + scheme) #3573 was about to land.server/src/db/federated-index-db.ts:378-505— dropupsertDiscoveredAgent,getDiscoveredAgents, related update/expire helpers.Crawler
server/src/crawler.ts— keepadagents.jsonparsing for the publisher-authorization graph (we still need to know who endorses whom forlist_authorized_propertiesvalidation), but stop registering unknown agents from those listings. The crawler becomes a verification tool for known agents, not a discovery tool for new ones.stats.discovered_agents(line 472) — remove.Database
discovered_agentstable — drop.discovered_publisherstable — drop, or preserve ascrawled_publishersif any publisher-graph code still needs the row (decide during impl).agent_publisher_authorizations— keep the table (authorizations still matter), but thesource: 'agent_claim' | 'adagents_json'enum stays meaningful only as an audit field, not as a registry-source signal.UI
server/public/agents.html— remove any source badge/filter/segment./registrypage — single list, no tabs.Docs
docs/registry/registering-an-agent.mdx— collapse the "four crawl paths" framing to "one path: enroll on your member profile."docs/registry/index.mdxoverview — drop the registered-vs-discovered explainer.endorsed_by_publisher_memberanddiscovered_fromreferences throughout.Tests
server/tests/unit/registry-discovered-endorsement.test.ts, the discovered branches of registry-sync tests.sourceor merged-list behavior.What we lose, and why it's fine
endorsed_by_publisher_member). Shipped two days ago in decision(registry): how should discovered agents surface member-publisher endorsement (#3538 Problem 6) #3547, deleted here. Net: the right move. The signal was a workaround for a category we are now removing.adagents.jsonentry pointing at an unregistered URL — a stronger nudge than "you're already in the registry, ish."?source=discovered. The?source=param is days old; risk is near zero.Migration plan
REGISTRY_HIDE_DISCOVERED=true(default true in prod) that filters discovered out of/api/registry/agents+ UI. No schema or DB changes. Ship behind flag, validate.source/discovered_from/endorsed_by_publisher_memberfrom response schemas and TS types. Update OpenAPI / docs.federated-index.tsmerge logic. Dropdiscovered_agents/discovered_publisherstables in a migration. Repoint crawler to verification-only mode.Open questions
agent_publisher_authorizationspopulated from crawl? Probably yes —list_authorized_propertiesvalidation still depends on it. The change is "we record the relationship; we do not turn the relationship into a registry entry."Acceptance
count(*)on/api/registry/agentsmatchescount(*)onmember_profiles.agentsafter dedup.discovered,discovered_from,endorsed_by_publisher_memberoutside of migration history.discovered_agentsanddiscovered_publisherstables are dropped (or renamed to reflect their crawler-graph-only role).