Story-748 docs lane Priority P0 Walkthrough

ADR-070 locks the pramaan-agents architecture

The doctrine Story that stopped agent implementation from starting on the wrong foundation.

Pull Request
Built by
Conductor agent on 2026-05-21

TL;DR

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.

Part One - What we planned to do and why

1 Why exists

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.

Physical mental model: choosing the building site before pouring concrete

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.

Ask yourself

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.

2 Plan + SVG diagram

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.

Story-748 documentation flow Story-748 converts Ankit's eight decisions into ADR-070 and registry entries, with the new Story-owned files highlighted in green. Q1-Q8 decisions Ankit, 2026-05-20 locked architecture ADR-070 Story-748 owned new agents repo Pattern C streaming big-bang trade-off Future work replacement Epic repo-local Stories ADR registry row Story-748 owned human index JSON registry Story-748 owned machine routing 1 codify 2 unlock 3 register 4 route

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.

Ask yourself

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.

Part Two - How we actually did it

3 What got built

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.

Read in this order

  1. docs/decisions/adrs/ADR-070-pramaan-agents-v1-architecture.md - the decision itself.
  2. docs/decisions/adrs/ADR-REGISTRY.md - the human-facing index entry.
  3. docs/decisions/adrs/adr-registry.json - the machine-readable routing entry.
docs/decisions/adrs/ADR-070-pramaan-agents-v1-architecture.md new ADR, 375 added lines

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.

docs/decisions/adrs/ADR-REGISTRY.md human registry, 1 added line

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.

docs/decisions/adrs/adr-registry.json machine registry, 16 added lines

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.

Ask yourself

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.

4 Deviations

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.

5 Errors

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.

6 Gotchas

Gotcha

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.

Gotcha

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.

Gotcha

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.

7 What's still open

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.

8 Check yourself

Questions a future engineer should be able to answer

  1. Which part of ADR-069 does ADR-070 supersede, and which part stays in force?
  2. Why does pramaan-functions still own migrations even though agent runtime code moved to pramaan-agents?
  3. What are the two reasons Ankit accepted the big-bang delivery cost?
  4. In Pattern C, what job does SQS do that WebSocket alone cannot do?
  5. What makes MatterChatAgent v1 different from a generic chatbot?
  6. Why do both the Markdown ADR registry and JSON ADR registry need updates?
  7. If a future engineer wants to add sub-agents, why should they not treat ADR-070 as already authorizing that v1 behavior?

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.