This runbook is for engineers operating, debugging, or extending the shipped Sentiment Simulator workflow locally.
This document assumes you are working on the current launch path:
- product seed
- graph build
- campaign creation
- asynchronous preparation
- parallel scenario execution
- sentiment dashboard
It focuses on:
- local setup
- required environment variables
- how to start the stack
- how to verify each stage
- where runtime artifacts live
- how to debug failures quickly
Required versions from the repo:
- Node.js
18+ - Python
3.11+ uv
Useful checks:
node -v
python --version
uv --versionCreate .env in the project root and set at least:
SECRET_KEY=replace-me
LLM_API_KEY=replace-me
ZEP_API_KEY=replace-me
LLM_BASE_URL=https://api.openai.com/v1
LLM_MODEL_NAME=gpt-4o-mini
FRONTEND_ORIGIN=http://localhost:3000
CORS_ORIGINS=http://localhost:3000
VITE_API_BASE_URL=http://localhost:5001Important runtime behavior:
backend/run.pyvalidatesSECRET_KEY,LLM_API_KEY, andZEP_API_KEYbefore startup- if any are missing, the backend exits immediately
FLASK_DEBUGdefaults tofalseSERVE_FRONTENDdefaults totrue
Useful optional variables:
FLASK_DEBUG=true
FLASK_HOST=0.0.0.0
FLASK_PORT=5001
LOG_REQUEST_BODIES=true
SENTIMENT_DEFAULT_TOTAL_AGENTS=50
SENTIMENT_DEFAULT_MAX_ROUNDS=20
SENTIMENT_SCENARIO_B_INJECT_ROUND=7
SENTIMENT_SCENARIO_C_INJECT_ROUND=14From the repo root:
npm install
npm install --prefix frontend
cd backend && uv sync --frozenEquivalent repo scripts:
npm run setup
npm run setup:backendFrom the repo root:
npm run devThis starts:
- backend on
http://localhost:5001 - frontend on
http://localhost:3000
Backend:
npm run backendFrontend:
npm run frontenddocker compose up --buildThis builds the frontend once and serves the app through the backend container on port 5001.
curl http://localhost:5001/healthExpected:
{"status":"ok","service":"sentiment-simulator-backend"}Open:
http://localhost:3000during local split frontend/backend developmenthttp://localhost:5001when using the container or backend-served frontend
In frontend dev mode, VITE_API_BASE_URL should point at the backend:
http://localhost:5001
If it is empty or wrong, the UI will load but API calls will fail or hit the wrong origin.
Use this order when checking whether the product is working.
Expected behavior:
- the form submits
- preview generation succeeds
- no validation errors for required fields
Relevant endpoints:
POST /api/sentiment/seed/validatePOST /api/sentiment/seed/preview
Expected behavior:
- a project is created
- uploaded file is saved
- ontology and analysis summary are returned
Artifacts to inspect:
backend/uploads/projects/<project_id>/project.jsonbackend/uploads/projects/<project_id>/extracted_text.txt
Expected behavior:
- graph build task starts
- polling progresses from pending to processing to completed
- graph preview renders
Artifacts to inspect:
backend/uploads/tasks/<task_id>.jsonproject.jsoncontainsgraph_id
Expected behavior:
- campaign is created with
sim_id_a,sim_id_b,sim_id_c - prepare endpoint creates a task
- status polling reaches
completed
Artifacts to inspect:
backend/uploads/campaigns/<campaign_id>/campaign.jsonbackend/uploads/simulations/<simulation_id>/state.jsonbackend/uploads/simulations/<simulation_id>/simulation_config.jsonbackend/uploads/simulations/<simulation_id>/archetype_map.json
Expected behavior:
- campaign status becomes
running - each scenario gains a
run_state.json - action logs appear under
twitter/andreddit/
Artifacts to inspect:
backend/uploads/simulations/<simulation_id>/run_state.jsonbackend/uploads/simulations/<simulation_id>/simulation.logbackend/uploads/simulations/<simulation_id>/twitter/actions.jsonlbackend/uploads/simulations/<simulation_id>/reddit/actions.jsonl
Expected behavior:
- dashboard loads scenario analytics
- comparison view returns a unified round axis
- a sentiment cache file is written
Artifacts to inspect:
backend/uploads/simulations/<simulation_id>/sentiment_cache.json
The fastest way to debug this product is to know where state lives.
backend/uploads/
campaigns/
camp_xxx/
campaign.json
projects/
proj_xxx/
files/
extracted_text.txt
project.json
simulations/
sim_xxx/
state.json
run_state.json
simulation_config.json
reddit_profiles.json
twitter_profiles.csv
archetype_map.json
sentiment_cache.json
simulation.log
twitter/
actions.jsonl
reddit/
actions.jsonl
tasks/
task_xxx.json
Use when debugging:
- project lifecycle
- ontology generation
- graph build linkage
Use when debugging:
- graph build progress
- campaign preparation progress
Use when debugging:
- scenario IDs
- campaign lifecycle status
- injection scheduling
- preparation progress
Use when debugging:
- whether a simulation was prepared successfully
- whether profiles and config generation completed
Use when debugging:
- current round
- runner status
- recent actions
- process state
Use when debugging:
- subprocess startup failure
- OASIS runtime issues
- crashes not clearly visible in the frontend
Use when debugging:
- whether agents are producing output
- whether event injections happened
- whether sentiment analysis has content to classify
Use when debugging:
- cache hits
- stale analytics
- whether analysis output was persisted
Check:
- missing
SECRET_KEY - missing
LLM_API_KEY - missing
ZEP_API_KEY
The backend entrypoint validates these before launching Flask.
Check:
VITE_API_BASE_URL- backend is actually running on
5001 CORS_ORIGINSandFRONTEND_ORIGIN
Check:
backend/uploads/tasks/<task_id>.json- backend logs for Zep API failures
- whether
ZEP_API_KEYis valid - whether the project has extracted text and ontology saved correctly
Check:
campaign.json- corresponding preparation task JSON
state.jsonfor eachsim_id_*- backend logs for LLM or config-generation failures
Check:
simulation_config.jsonexistsrun_state.jsonexistssimulation.logfor subprocess errors- whether
twitter/actions.jsonlorreddit/actions.jsonlare being created
Check:
- whether there are any action logs at all
- whether posts were created instead of only non-content actions
sentiment_cache.json- backend logs for sentiment classification failures
When something breaks, use this order:
- Check the browser network request that failed.
- Check the matching persisted JSON or log file under
backend/uploads/. - Check backend console output.
- Check the owning service class.
- Only then start changing prompts, thresholds, or models.
This order matters because many failures are orchestration or file-state issues, not model-quality issues.
curl http://localhost:5001/healthcurl -X POST http://localhost:5001/api/sentiment/seed/validate \
-H 'Content-Type: application/json' \
-d '{
"product_name":"Signal Desk",
"product_category":"B2B SaaS",
"tagline":"Run launch decisions with evidence",
"target_market":"Product marketers",
"core_features":[{"name":"Launch monitoring","description":"Tracks reactions"}],
"pricing_tiers":[{"name":"Growth","price":"$99","description":"Small teams"}]
}'curl http://localhost:5001/api/graph/task/<task_id>curl http://localhost:5001/api/sentiment/campaign/<campaign_id>curl http://localhost:5001/api/sentiment/campaign/<campaign_id>/sentimentBackend tests:
backend/.venv/bin/python -m pytest -q backend/testsWhat the current test suite is most useful for:
- launch sentiment routes
- task manager behavior
- sentiment cache behavior
It is not a full end-to-end simulation reliability suite.
This system persists state aggressively. Old runs can confuse debugging if you forget they exist.
Common places to inspect or clean manually:
backend/uploads/projects/backend/uploads/tasks/backend/uploads/campaigns/backend/uploads/simulations/
Be careful when deleting persisted state if you are sharing the workspace with someone else or comparing runs.
The current shipped path has a few important constraints:
- campaign preparation is asynchronous
- scenario execution is parallel
- launch population generation is archetype-based
- sentiment analysis is cached
- the public frontend is narrowed to the sentiment workflow
If your debugging assumptions conflict with any of those, update the assumption first.
Inspect backend/app/services/seed_template_processor.py when:
- seed validation is wrong
- preview text is poor
- downstream prompt context is incomplete
Inspect backend/app/services/campaign_manager.py when:
- preparation status looks wrong
- scenarios do not start together
- injection timing is wrong
- campaign status aggregation is wrong
Inspect backend/app/services/simulation_manager.py when:
- profile files are missing
- config files are malformed
- simulation preparation fails before runtime
Inspect backend/app/services/simulation_runner.py when:
- subprocesses never start
- runs stall
- action logs are not parsed
- run-state polling is wrong
Inspect backend/app/services/sentiment_analyzer.py when:
- sentiment scores are missing or stale
- objections or topics look wrong
- cache invalidation seems broken
If you want to sanity-check the whole stack quickly:
- start backend and frontend
- confirm
/health - submit a minimal valid seed
- confirm graph build task completion
- confirm campaign preparation completion
- confirm
simulation.logandactions.jsonlare being written - confirm the dashboard writes
sentiment_cache.json
If all seven happen, the launch workflow is functioning end to end.