The doctrine Story that stopped agent implementation from starting on the wrong foundation.
Story-748 added ADR-070, the decision record that says product-agent code belongs in a new internal-only pramaan-agents runtime, not inside the old pramaan-functions shape. It locks eight architecture choices: Strands as an SDK, same Postgres cluster, no public agent endpoint, static registries, WebSocket plus SQS streaming, big-bang delivery, MatterChatAgent v1, and a new repo with migrations still owned by pramaan-functions.
Before this Story, PRAMAAN had the storage boundary from ADR-069, but the runtime shape was still fuzzy. Some tickets assumed the agent code would begin inside pramaan-functions and move out later. On 2026-05-20, Ankit made eight concrete decisions that changed that direction.
The job of Story-748 was to turn those decisions into durable doctrine before anyone wrote throwaway agent code. That matters because architecture is cheap to correct while it is still a document and expensive to correct after CI, deploy, queues, tables, UI, and IAM all depend on it.
Imagine you are building a kitchen for a restaurant. You can argue about the oven brand later, but you cannot start pouring the concrete slab while still undecided about whether the kitchen belongs inside the dining room or in a separate service building. Story-748 picked the service building: pramaan-agents gets its own runtime and repo, while pramaan-functions remains the public front desk and migration owner.
If ADR-069 already created the agents schema boundary, why did PRAMAAN still need ADR-070 before implementation?
Answer: ADR-069 answered where agent state lives. ADR-070 answers where agent code runs, how the browser receives slow AI output, and which repo owns the runtime. Storage and deployment are related, but they are not the same decision.
The plan was intentionally narrow: write ADR-070, register it, and avoid inventing new architecture beyond Ankit's Q1-Q8 decisions. The Story body already contained the locked decisions, so the implementation was a codification task, not a fresh design session.
The green boxes are the Story-748 changes: the new ADR and the two registry updates. The arrows show the reading logic. The Story starts with locked decisions, produces a decision record, then makes that decision discoverable by both humans and tooling.
Why does the diagram show registry files as part of the plan instead of treating them as boring bookkeeping?
Answer: In this repo, path stability and registry discovery are product behavior. If ADR-070 exists but the registry cannot route readers to it, future agents and engineers have to search by memory. The registry is the library card catalog, not a decoration.
PR #82 added 392 lines across 3 files: one new ADR, one Markdown registry row, and one JSON registry object. There were no deletions. Read the work in this order, because that matches how understanding builds.
docs/decisions/adrs/ADR-070-pramaan-agents-v1-architecture.md - the decision itself.docs/decisions/adrs/ADR-REGISTRY.md - the human-facing index entry.docs/decisions/adrs/adr-registry.json - the machine-readable routing entry.This is the main artifact. It says pramaan-agents is a new internal runtime, Strands is a Python SDK installed inside that Lambda, Bedrock Converse is the model API underneath, and Pattern C is the streaming path: browser WebSocket to API Gateway, through pramaan-functions, into SQS, then into pramaan-agents, then back to the browser through postToConnection.
The most important teaching point is the split between three boundaries: pramaan-functions remains the public/auth/migration boundary, pramaan-agents becomes the internal agent runtime boundary, and SQS plus WebSocket becomes the bridge for slow streaming work.
This adds ADR-070 to the table with category Infra, status accepted, date 20 May 2026, and affected repos pramaan-agents, pramaan-functions, pramaan-app, pramaan-docs, and pramaan-spec.
Think of this as the shelf label. The ADR is the book; the registry row is how a tired engineer finds the book without already knowing the title.
This adds the machine-readable ADR-070 object with active routing metadata, affected repos, tags, supersession information, and links to related ADRs. It records that ADR-070 supersedes the implicit deployment assumption from ADR-069 while extending ADR-022, ADR-037, ADR-054, ADR-055, ADR-068, and ADR-069.
The JSON matters because future automation can answer "which ADRs affect pramaan-agents?" without scraping Markdown tables.
What is the fastest way to misread ADR-070?
Answer: Treating "new repo" as "new database owner." ADR-070 separates runtime code, but it keeps migrations in pramaan-functions because the agents schema has cross-schema relationships to existing business and identity tables.
The landed PR stayed close to the issue. It wrote ADR-070, included the architecture diagram, named the superseded tickets, listed out-of-scope work, and updated both registries.
The important deviation is historical rather than mechanical: the ADR records Ankit choosing big-bang delivery and a new repo against the phased same-repo recommendation from Claude/docs-agent. The PR did not smooth that disagreement away. It preserved the trade-off so future readers know the slower demo path was a conscious choice, not drift.
There was also one wording nuance: ADR-070 does not supersede all of ADR-069. It supersedes only the implicit assumption that agent code would run in the pramaan-functions Lambda deployment shape. ADR-069 still governs the Postgres namespace and storage boundary.
No implementation error is recorded in PR #82's body. The verification commands passed: JSON parsing, retired runtime search, ADR counts, registry row counts, and diff whitespace checks.
The hidden failure mode this Story avoided was starting implementation from the wrong ticket shape. Epic-745, Story-746, and Story-747 had been filed under the older phased/same-functions assumption. ADR-070 names that mismatch directly so cleanup can happen as follow-up work instead of letting old tickets quietly steer new code.
Internal-only does not mean "skip authorization thinking." ADR-070 removes public HTTP exposure from pramaan-agents, but pramaan-functions still owns the public Clerk-authenticated boundary. The wall socket moved; the wiring still needs a breaker.
Big-bang is not the same as "everything in one repo." The Epic is big-bang because Pattern C, the agent runtime, and the app streaming client must land together. The implementation still decomposes into repo-local Stories because ADR-031 keeps executable work inside the repo that owns it.
Pattern C is a user-experience decision as much as an infra decision. SQS handles slow work and retries; WebSocket makes the browser feel alive while the AI streams. If you remove either half, the product shape changes.
ADR-070 is a lock, not the implementation itself. It enables the next wave of work: replacing the old Epic shape, bootstrapping pramaan-agents, adding the agents schema migration in pramaan-functions, provisioning SQS/WebSocket/IAM, building the SQS consumer and Strands harness, implementing MatterChatAgent v1, and adding the app chat UI.
The ADR also leaves several things intentionally out of scope: sub-agent architecture, plan mode, the product-facing agent name, separate Aurora/Postgres, frontend WebSocket implementation details, and specific tool implementation details.
pramaan-functions still own migrations even though agent runtime code moved to pramaan-agents?If those answers are clear, you understand the real Story: this PR did not build the agent. It made sure the team would build the agent in the right building, through the right front door, with the right streaming pipe.