{"id":51502752,"url":"https://github.com/blanzy-labs/ai-council","last_synced_at":"2026-07-07T21:01:42.044Z","repository":{"id":368495262,"uuid":"1284982518","full_name":"blanzy-labs/ai-council","owner":"blanzy-labs","description":"A local-first app for collecting and comparing responses from an AI council. Part of the Blanzy Labs AI app family.","archived":false,"fork":false,"pushed_at":"2026-06-30T19:59:41.000Z","size":109,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-30T21:25:41.985Z","etag":null,"topics":["ai","blanzy-labs","council","docker","fastapi","llm","local-first","openai","react","sse","vite"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blanzy-labs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security-and-privacy.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-30T11:21:41.000Z","updated_at":"2026-06-30T19:59:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/blanzy-labs/ai-council","commit_stats":null,"previous_names":["blanzy-labs/ai-council"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/blanzy-labs/ai-council","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blanzy-labs%2Fai-council","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blanzy-labs%2Fai-council/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blanzy-labs%2Fai-council/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blanzy-labs%2Fai-council/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blanzy-labs","download_url":"https://codeload.github.com/blanzy-labs/ai-council/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blanzy-labs%2Fai-council/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35242497,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-07T02:00:07.222Z","response_time":90,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","blanzy-labs","council","docker","fastapi","llm","local-first","openai","react","sse","vite"],"created_at":"2026-07-07T21:01:41.151Z","updated_at":"2026-07-07T21:01:42.038Z","avatar_url":"https://github.com/blanzy-labs.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AI Council\n\nA local-first, text-based multi-persona AI council room for structured discussion, critique, follow-up chat, live activity events, and transcript export.\n\nPart of the Blanzy Labs AI app family.\n\n**Current release:** v0.1.2 - Blanzy Labs Standardization Patch\n\nAI Council v0.1.x is intended for local testing, demos, and iteration. It runs with a deterministic mock provider by default for safe local workflows, and can call OpenAI only when explicitly configured and selected.\n\nSee the [disclaimer](docs/disclaimer.md) before using AI Council. You are responsible for your own usage, costs, data, decisions, and outcomes.\n\n## Current Scope\n\n- OpenAI provider support\n- Mock provider for local testing without `OPENAI_API_KEY`\n- Multi-persona council sessions\n- Default personas\n- Structured council run\n- Follow-up chat\n- Ask whole council\n- Ask one persona\n- Server-Sent Events live activity events\n- Markdown export\n- JSON export\n- In-memory sessions/transcripts/events only\n- Docker Compose local run\n\n## Out Of Scope For v0.1.x\n\n- Voice\n- Gemini\n- Database persistence\n- User accounts\n- Telemetry\n- Hosted deployment\n- Long-term session history\n- Token-by-token model streaming\n- Autonomous/open-ended agent loops\n\n## Roadmap\n\n- v0.2.0: voice experiments using OpenAI only\n- v0.3.0: Gemini provider adapter exploration\n\n## Architecture Overview\n\n- FastAPI backend exposes personas, sessions, council runs, chat, events, exports, health, and version metadata.\n- React/Vite frontend provides the local app UI.\n- Provider adapter layer normalizes mock and OpenAI responses behind one interface.\n- Persona registry provides the default council personas.\n- In-memory session, transcript, and event stores hold runtime state only.\n- SSE event stream powers live activity updates.\n- Export service generates Markdown and JSON from the current in-memory session state.\n- Docker Compose runs backend and frontend together for local validation.\n\nThere is no database in v0.1.x. Restarting the backend loses sessions, transcripts, events, and exportable state.\n\n## Local Setup\n\nFor the standalone setup guide, see [Local Install](docs/local-install.md).\n\nPrerequisites:\n\n- Git\n- Python 3.13\n- `uv`\n- Node.js and `pnpm`\n- Docker Desktop or Docker daemon, if using Docker Compose\n\nCopy the example environment file:\n\n```sh\ncp .env.example .env\n```\n\nOnly set `OPENAI_API_KEY` if you are manually testing OpenAI. Mock mode and normal tests do not require an API key.\n\nBackend:\n\n```sh\ncd backend\nuv sync\nuv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000\n```\n\nFrontend:\n\n```sh\ncd frontend\npnpm install\npnpm dev\n```\n\nLocal URLs:\n\n- Frontend: http://localhost:5173\n- Backend: http://localhost:8000\n- API docs: http://localhost:8000/docs\n- Health: http://localhost:8000/health\n- Version: http://localhost:8000/version\n\n## Docker Setup\n\nBuild and start both services:\n\n```sh\ndocker compose up --build\n```\n\nExpected URLs:\n\n- Frontend: http://localhost:5173\n- Backend: http://localhost:8000\n- Health: http://localhost:8000/health\n\nStop services:\n\n```sh\ndocker compose down\n```\n\n## Testing\n\nBackend tests:\n\n```sh\ncd backend\nuv run pytest\n```\n\nFrontend build:\n\n```sh\ncd frontend\npnpm build\n```\n\nDocker build:\n\n```sh\ndocker compose build\n```\n\nOptional real OpenAI smoke test:\n\n```sh\ncd backend\n# Set OPENAI_API_KEY in your shell first.\nRUN_OPENAI_INTEGRATION_TESTS=1 uv run pytest tests/test_openai_integration.py -m integration\n```\n\nNormal tests skip real OpenAI calls.\n\n## Usage Workflow\n\n1. Create session.\n2. Select personas.\n3. Run council.\n4. Continue chat.\n5. Watch live activity.\n6. Export transcript.\n\nRecommended local testing path: use `provider_override: \"mock\"` in run/chat requests, or select `mock` in the frontend.\n\n## API Summary\n\n- `GET /`\n- `GET /health`\n- `GET /version`\n- `GET /personas`\n- `GET /personas/{persona_id}`\n- `POST /providers/test-generate`\n- `POST /sessions`\n- `GET /sessions`\n- `GET /sessions/{session_id}`\n- `POST /sessions/{session_id}/run`\n- `POST /sessions/{session_id}/chat`\n- `GET /sessions/{session_id}/messages`\n- `DELETE /sessions/{session_id}/messages`\n- `GET /sessions/{session_id}/events`\n- `GET /sessions/{session_id}/events/recent`\n- `DELETE /sessions/{session_id}/events`\n- `GET /sessions/{session_id}/result`\n- `POST /sessions/{session_id}/export`\n- `GET /sessions/{session_id}/export/markdown`\n- `GET /sessions/{session_id}/export/json`\n\n## Curl Examples\n\nMetadata:\n\n```sh\ncurl http://localhost:8000/\ncurl http://localhost:8000/health\ncurl http://localhost:8000/version\n```\n\nCreate a session:\n\n```sh\ncurl -X POST http://localhost:8000/sessions \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"title\": \"Local-first AI Council\",\n    \"topic\": \"Should AI Council be built as a local-first multi-persona app?\",\n    \"mode\": \"ask_council\",\n    \"selected_persona_ids\": [\n      \"moderator\",\n      \"strategist\",\n      \"skeptic\",\n      \"builder\",\n      \"customer_advocate\"\n    ]\n  }'\n```\n\nRun council with mock:\n\n```sh\ncurl -X POST http://localhost:8000/sessions/\u003cSESSION_ID\u003e/run \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"provider_override\": \"mock\",\n    \"max_rounds\": 1,\n    \"include_moderator_summary\": true\n  }'\n```\n\nAsk the whole council:\n\n```sh\ncurl -X POST http://localhost:8000/sessions/\u003cSESSION_ID\u003e/chat \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"message\": \"What is the riskiest assumption in this plan?\",\n    \"target\": {\n      \"type\": \"council\"\n    },\n    \"provider_override\": \"mock\",\n    \"include_moderator_summary\": false\n  }'\n```\n\nAsk one persona:\n\n```sh\ncurl -X POST http://localhost:8000/sessions/\u003cSESSION_ID\u003e/chat \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"message\": \"What is the smallest useful MVP?\",\n    \"target\": {\n      \"type\": \"persona\",\n      \"persona_id\": \"builder\"\n    },\n    \"provider_override\": \"mock\",\n    \"include_moderator_summary\": false\n  }'\n```\n\nRecent events:\n\n```sh\ncurl http://localhost:8000/sessions/\u003cSESSION_ID\u003e/events/recent\n```\n\nLive SSE stream:\n\n```sh\ncurl -N http://localhost:8000/sessions/\u003cSESSION_ID\u003e/events\n```\n\nInline Markdown export:\n\n```sh\ncurl -X POST http://localhost:8000/sessions/\u003cSESSION_ID\u003e/export \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"format\": \"markdown\",\n    \"include_events\": false,\n    \"include_metadata\": true\n  }'\n```\n\nInline JSON export:\n\n```sh\ncurl -X POST http://localhost:8000/sessions/\u003cSESSION_ID\u003e/export \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"format\": \"json\",\n    \"include_events\": true,\n    \"include_metadata\": true\n  }'\n```\n\nDirect downloads:\n\n```sh\ncurl -OJ http://localhost:8000/sessions/\u003cSESSION_ID\u003e/export/markdown\ncurl -OJ http://localhost:8000/sessions/\u003cSESSION_ID\u003e/export/json\n```\n\nClear runtime state:\n\n```sh\ncurl -X DELETE http://localhost:8000/sessions/\u003cSESSION_ID\u003e/messages\ncurl -X DELETE http://localhost:8000/sessions/\u003cSESSION_ID\u003e/events\n```\n\n## Troubleshooting\n\nFor the standalone troubleshooting guide, see [Troubleshooting](docs/troubleshooting.md).\n\nDocker Desktop not running:\n\n- Start Docker Desktop or your Docker daemon.\n- Rerun `docker compose up --build`.\n\nPorts `8000` or `5173` already in use:\n\n- Stop the process using the port, or adjust `BACKEND_PORT` / `FRONTEND_PORT` in `.env`.\n\nFrontend cannot reach backend:\n\n- Confirm backend health: `curl http://localhost:8000/health`.\n- Confirm `VITE_API_BASE_URL=http://localhost:8000`.\n- If using Docker, run `docker compose ps`.\n\nOpenAI key missing:\n\n- Mock mode works without a key.\n- Real OpenAI calls require `OPENAI_API_KEY`.\n- Missing keys return a clean API error and do not prevent app startup.\n\nMock works but OpenAI fails:\n\n- Confirm `OPENAI_API_KEY` is set in `.env` or the backend environment.\n- Confirm the selected provider is `openai`.\n- Check backend logs for provider errors.\n\nSessions disappear after restart:\n\n- Expected in v0.1.x. Runtime state is in memory only.\n\nCORS/local URL issues:\n\n- Default allowed frontend origins are `http://localhost:5173` and `http://127.0.0.1:5173`.\n- Add comma-separated local origins with `CORS_ORIGINS` if needed.\n\n## Documentation\n\n- [v0.1.0 scope](docs/v0.1.0-scope.md)\n- [release notes v0.1.0](docs/release-notes/v0.1.0.md)\n- [release notes v0.1.1](docs/release-notes/v0.1.1.md)\n- [release notes v0.1.2](docs/release-notes/v0.1.2.md)\n- [GitHub release notes](docs/github-release-notes.md)\n- [demo guide](docs/demo.md)\n- [local install](docs/local-install.md)\n- [troubleshooting](docs/troubleshooting.md)\n- [disclaimer](docs/disclaimer.md)\n- [validation checklist](docs/validation/v0.1.0-validation.md)\n- [validation v0.1.2](docs/validation/v0.1.2-validation.md)\n- [architecture notes](docs/architecture.md)\n- [security and privacy notes](docs/security-and-privacy.md)\n- [sample scenarios](docs/sample-scenarios.md)\n- [release checklist](docs/release-checklist.md)\n- [license](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblanzy-labs%2Fai-council","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblanzy-labs%2Fai-council","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblanzy-labs%2Fai-council/lists"}