hp-studios-ai-content-agent/SPEC.md
DJP 72c8a0d0fe Initial import — HP Studios AI Content Agent
Full-stack app that turns HP customer briefs (master asset + regional
supporting docs) into a set of branded Word deliverables via a RAG +
agent pipeline.

Stack
- FastAPI + SQLAlchemy + pgvector + RQ (backend, Python 3.12)
- React + Vite + TypeScript + Tailwind + TanStack Query (frontend)
- Claude Opus 4.7 (generation) + Haiku 4.5 (translation/OCR)
- Voyage voyage-3 or OpenAI text-embedding-3-small (embeddings)
- python-docx (branded Word output, Montserrat + HP blue)
- Docker Compose (5 services)

Features
- 6 built-in deliverable types (leadership themes, regional enrichment,
  LinkedIn posts, webinar spec, infographic specs, ABM enablement)
- Data-driven deliverable types: admins add new types at runtime via
  prompt + JSON schema + template_json — no code, no deploy
- Generic schema-driven review form + generic Word template renderer
- Document ingestion pipeline with translation, chunking, pgvector RAG
- Pluggable auth provider (password now, Entra SSO later); admin/user roles
- Re-roll / retry on every deliverable; cascading delete; brief editing;
  inline document upload; progress hints; router-level ErrorBoundary
- Admin panel with test-render preview for new deliverable types
- Help page at /help with architecture overview and usage guide

82 backend tests passing, 18 skipped (gated live-API tests).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 17:11:25 -04:00

5.5 KiB

HP Content Agent App — Shared Build Spec

This is the contract between parallel builders. Honour it exactly so the pieces fit.

Monorepo root

/Users/daveporter/Desktop/CODING-2024/HP-TASKS/app/

Python

Python 3.12. Backend package root: backend/app/. Use pyproject.toml in backend/.

Deliverable types (enum — use these exact strings everywhere)

  • leadership_themes
  • regional_enrichment
  • linkedin_posts
  • webinar_spec
  • infographic_specs
  • abm_enablement

Module interfaces (cross-component contracts)

app.schemas (per deliverable)

  • from app.schemas.leadership_themes import LeadershipThemes
  • One top-level pydantic BaseModel per deliverable type, file named after the type.
  • Each exposes .model_json_schema() for Claude tool schemas.
  • Also export a map: app.schemas.registry.SCHEMA_BY_TYPE: dict[str, type[BaseModel]]

app.hp_branding.render

  • render_to_bytes(deliverable_type: str, content: dict) -> bytes — returns .docx bytes.
  • Internally dispatches to renderers/<type>.py with a render(doc_content) -> Document or similar.

app.agents.generate

  • generate_deliverable(brief_id: UUID, deliverable_type: str, session: Session) -> dict — returns validated structured content (already dict-form of the pydantic schema).
  • Internally: loads brief + retrieved chunks + system prompt, calls Claude with tool_choice, parses, validates.

app.ingestion.orchestrator

  • ingest_document(document_id: UUID, session: Session) -> None — synchronous; called by RQ worker. Extracts text, translates, chunks, embeds, persists.

app.workers.tasks

  • ingest_document_task(document_id) — RQ task wrapping ingestion.
  • generate_deliverable_task(generation_id) — RQ task wrapping agent. Updates generations.status and structured_content.

DB schema (SQLAlchemy + pgvector)

Tables:

  • users(id uuid pk, email unique, name, password_hash, role text check role in ('admin','user'), created_at)
  • briefs(id uuid pk, name, region, audience, brief_text, created_by fk users, created_at)
  • documents(id uuid pk, brief_id fk briefs cascade, kind text check kind in ('master','supporting'), filename, storage_path, mime_type, language, page_count, extracted_text text, translated_text_en text, uploaded_at, ingestion_status text default 'pending')
  • doc_chunks(id uuid pk, document_id fk documents cascade, chunk_index int, text text, embedding vector(1024)) — use Voyage voyage-3 (1024 dims) OR Anthropic-compatible. If Voyage not available, use vector(1536) and OpenAI text-embedding-3-small.
  • generations(id uuid pk, brief_id fk briefs, deliverable_type text, status text, structured_content jsonb, tokens_used int, cost_usd numeric, error text, started_at, completed_at)
  • exports(id uuid pk, generation_id fk generations, docx_path text, generated_at)

REST API (stable paths for frontend)

All JSON unless noted. Auth via Authorization: Bearer <jwt> OR access_token httpOnly cookie.

  • POST /auth/login {email, password} → {access_token, user}
  • POST /auth/logout
  • GET /auth/me → current user
  • POST /users (admin only) {email, name, password, role}
  • GET /users (admin only)
  • GET /briefs — user sees own; admin sees all
  • POST /briefs {name, region, audience, brief_text}
  • GET /briefs/:id
  • POST /briefs/:id/duplicate → new brief id
  • DELETE /briefs/:id
  • POST /briefs/:id/documents (multipart) file, kind → document
  • GET /briefs/:id/documents
  • DELETE /documents/:id
  • POST /briefs/:id/generations {deliverable_types: string[]} → array of generation ids, jobs enqueued
  • GET /briefs/:id/generations → status + structured_content per deliverable
  • GET /generations/:id
  • PATCH /generations/:id {structured_content} — user edits
  • POST /generations/:id/export → {download_url}
  • GET /exports/:id/download → file

Frontend env

Base API URL from VITE_API_URL (default http://localhost:8000).

Docker services

  • postgres image pgvector/pgvector:pg16 port 5432
  • redis image redis:7-alpine port 6379
  • api build ./backend port 8000
  • worker build ./backend command rq worker default
  • frontend build ./frontend port 5173 (dev) or 80 (prod)

Secrets (via .env)

ANTHROPIC_API_KEY, VOYAGE_API_KEY (optional), OPENAI_API_KEY (optional, fallback embeddings), POSTGRES_USER=hp, POSTGRES_PASSWORD=hp, POSTGRES_DB=hp_content_agent, JWT_SECRET, REDIS_URL=redis://redis:6379/0.

Golden fixtures (for verification)

Existing files in /Users/daveporter/Desktop/CODING-2024/HP-TASKS/:

  • IT_moment_to_lead.pdf — master doc
  • POLISH/ — 6 supporting docs
  • HP_Four_Leadership_Themes.docx, HP_Poland_Enriched_Leadership_Themes.docx, HP_Task3_Content_Repurposing_Deliverables.docx — golden output references

Existing scripts (reference for porting branding, DO NOT re-import)

  • build_poland_enriched.py — Montserrat renderer with shade_cell, styled_table, add_body, add_quote, bullet, sub_bullet, add_scenario_box (lines ~53-134)
  • build_task3_deliverables.py — same palette + post_block helper for LinkedIn posts (lines ~89-118)
  • convert_to_docx.py — Calibri variant (older; use for structure only, standardise on Montserrat)
  • System prompt: HP_Content_Agent_System_Instructions.md — copy verbatim to backend/app/agents/prompts/system.md

Conventions

  • No secrets committed. .env gitignored.
  • All Python files typed; use from __future__ import annotations.
  • Frontend strict mode on.
  • Each component README-free unless truly needed; root README covers setup.