dropthejase splits the AI brain in two for table-style review

One assistant for general chat, a second one dedicated to spreadsheet-style document review - each with its own focused toolkit.

contract-reviewchat-ui

The dropthejase fork now runs two AI agents side by side instead of cramming everything into one. The general assistant keeps its own tool set; a new specialist handles tabular review - the spreadsheet-style view where a reviewer runs the same questions across a stack of documents and gets answers laid out row by row. Keeping the two separate stops the general chat from getting cluttered with review-table machinery it doesn't need.

Along the way the team moved the tabular agent's chat history out of the relational database and into S3 (Amazon's cheap file storage), matching how the main assistant already stores conversations. They also tried a blanket auto-retry on failed requests, found it caused stale data to linger on screen across the app, and pulled it back out - a small but honest course-correction worth noting.

So what Legal-ops leads evaluating review tooling should note the pattern: one agent per workflow keeps each one sharper than a single do-everything bot.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

13 commits from dropthejase/louis, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
1a79b1c0 Add louisTabular agent and wire tabular chat to AgentCore Jason Lee 2026-05-09 ↗ GitHub
commit body
- agents/app/tabular/: new Strands agent mirroring main structure; single
  read_table_cells tool; system prompt built per-request from review context
- backend: replace POST /:reviewId/chat (runLLMStream) with two thin endpoints:
  POST /:reviewId/chats (create) and POST /:reviewId/chats/:chatId/messages (persist)
- frontend: streamTabularChat now calls AgentCore louisTabular URL; TRChatPanel
  pre-creates chat record before streaming, persists turn after [DONE]
- config: NEXT_PUBLIC_AGENTCORE_TABULAR_URL added to config + env example
- docs: README and ARCHITECTURE updated
1fede12c feat(api): add resolve-batch endpoint to fix bulk accept/reject race condition Jason Lee 2026-05-12 ↗ GitHub
commit body
Single Lambda reads S3 once, applies all resolutions in memory, writes once.
Frontend handleAll sends one batch request per document instead of N parallel.
Also constrains agent to single-paragraph edits to avoid cross-para deletion failures.
6e5b266e fix(api): parse columns_config and shared_with JSON strings in tabular review responses Jason Lee 2026-05-13 ↗ GitHub
8a09da7b fix(api): parse columns_config and shared_with in PATCH tabular review response Jason Lee 2026-05-13 ↗ GitHub
a0d653c1 feat(tabular): optimistic update when adding documents to review Jason Lee 2026-05-13 ↗ GitHub
54fd7a39 feat(frontend): retry apiRequest once on 500 after 1.5s delay Jason Lee 2026-05-13 ↗ GitHub
720650fc revert(frontend): remove apiRequest retry - caused stale UI across endpoints Jason Lee 2026-05-13 ↗ GitHub
66a5cecb fix(tabular): fix generation failures - columns_config parse, Bedrock client, UUID cast Jason Lee 2026-05-13 ↗ GitHub
commit body
- Parse columns_config from RDS Data API string before use in generate endpoint
- Remove stale 'const client = client' self-references in bedrock.ts (ReferenceError)
- Rename queryGeminiAllColumns/queryGemini to queryBedrockAllColumns/queryBedrock
- Add ::uuid cast to :pid${i} params in shared-by-project query
e2ed854f fix(tabular-agent): fix credential bootstrap, columns_config parse, and UUID cast on document IN query Jason Lee 2026-05-14 ↗ GitHub
714bcbd1 fix(api): parse columns_config JSON string in workflow responses Jason Lee 2026-05-14 ↗ GitHub
commit body
Aurora Data API returns jsonb columns as raw strings. withWorkflowAccess
was spreading the raw DB row without parsing columns_config, causing
TypeError: .sort is not a function on the WorkflowPage and corrupt
double-serialized data when creating a tabular review from a custom workflow.

Parse in withWorkflowAccess so all workflow endpoints (GET /, GET /:id,
PUT, PATCH) are covered by a single fix.
8c7e7405 fix(tabular): parse jsonb content/annotations in mapTRMessages Jason Lee 2026-05-14 ↗ GitHub
42c8e187 fix(tabular): suppress CITATIONS from stream, fix citation schema and extraction Jason Lee 2026-05-14 ↗ GitHub
29b80f48 feat(tabular): migrate tabular chat storage from Aurora to S3 Jason Lee 2026-05-14 ↗ GitHub
commit body
Tabular review chat messages now stored in S3 (conversations/{chatId}/messages.json)
using the same Strands snapshot format as the main chat agent. This gives the tabular
agent full conversation history on every turn (agent memory).

- agent.ts: loadMessages (S3 GET) + AfterInvocationEvent hook (S3 PUT)
- index.ts: load previous messages, pass to createAgent, tail-buffer suppresses <CITATIONS>
- sessions.ts: new shared lib - S3 read/write + snapshotMessagesToSessionMessages
- chat.ts: remove ~250 lines of private session logic, import from sessions.ts
- tabular.ts: replace Aurora message reads/writes with S3 via sessions.ts
- mikeApi.ts + TRChatPanel.tsx: remove Aurora-specific message mapping

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-345.md from inside the repo you want the changes in.

⬇ Download capture-thread-345.md