Co pi podcast#1
Open
malanjary-tsri wants to merge 51 commits into
Open
Conversation
…ach PI
Adds a new podcast service that runs daily, searches PubMed for recent
publications relevant to each PI's profile, selects the most impactful
paper via Sonnet, generates a structured PI-specific summary via Opus,
produces audio via ElevenLabs TTS, delivers via Slack DM, and serves
episodes over a per-PI RSS podcast feed.
New modules:
- src/podcast/: scheduler (main.py), per-agent pipeline, PubMed query
builder, ElevenLabs TTS client, RSS feed builder, state persistence
- src/routers/podcast.py: /podcast/{agent_id}/feed.xml and audio endpoints
- src/models/podcast.py: PodcastEpisode DB model
- alembic/versions/0005_add_podcast_episodes.py: DB migration
- prompts/podcast-select.md + podcast-summarize.md: LLM prompt files
- specs/labbot-podcast.md: full feature specification
- templates/admin/podcast.html: admin dashboard tab
Wired into: FastAPI app, admin router, docker-compose (podcast service,
opt-in via --profile podcast), pyproject.toml (adds mutagen), config.py
(ElevenLabs + podcast env vars), and admin nav.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… log - Expose postgres port 5432 to host for local alembic/migrations and dev tooling - Gitignore data/ directory (runtime state: grantbot state, podcast audio/state) - Add .labbot-tests/podcast-run-2026-03-31.log capturing first successful podcast pipeline run (14 agents, text summaries generated via Claude, ElevenLabs skipped — no API key) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…test) Replaces elevenlabs.py with mistral_tts.py, which decodes the base64 JSON response, strips markdown from text before synthesis, and reads voice/model from new MISTRAL_* env vars. Adds a focused single-agent test script and .labbot-tests/ outputs from a successful run. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rking for local TTS. Adds podcast_data named volume shared between app and podcast services so audio files are accessible for serving; adds extra_hosts and LOCAL_TTS_HOST override in dev compose so the podcast container can reach a vLLM-Omni server running on the host. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…U R128, -16 LUFS). Adds normalize_audio() to tts_utils.py called by both Mistral and local TTS backends after saving audio; adds ffmpeg to Dockerfile so normalization works inside containers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Preprints are fetched concurrently with PubMed results and merged into the candidate pool; preprint IDs use a prefixed format (biorxiv:/medrxiv:/arxiv:) so deduplication and delivery tracking work without changes to state.py. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds tech stack, project structure, key commands, podcast pipeline overview, pilot lab roster, and architectural decisions so future sessions have complete context without re-exploring the codebase. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add ## Podcast Preferences section to all 14 private profiles so PIs
can tune article selection and summary tone via standing instructions
- Wire _load_podcast_preferences() into pipeline selection and summarize
steps; inject preferences into both prompts via {preferences} placeholder
- Add podcast_voices.json (gitignored data/) with per-agent voice overrides;
falls back to MISTRAL_TTS_DEFAULT_VOICE / LOCAL_TTS_VOICE env vars
- Add PODCAST_NORMALIZE_AUDIO config flag (default false); ffmpeg loudnorm
now only runs when explicitly enabled, fixing cross-device link error
- Remove unused elevenlabs.py dead code
- Update test_podcast_su.py to load and pass private profile preferences
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- src/main.py: restore invite/settings routers and full delegate-aware
AgentBadgeMiddleware from main; add podcast router alongside them
- src/models/__init__.py: restore AgentDelegate, DelegateInvitation,
EmailNotification, EmailEngagementTracker, ProfileRevision from main;
keep PodcastEpisode alongside them
- pipeline.py: _load_podcast_preferences() now reads the ## Podcast
Preferences section from the latest private ProfileRevision in the DB
(async, self-contained) instead of flat files on disk
- docker-compose.yml: use ${POSTGRES_USER:-copi} env-var style matching
main; remove hardcoded DATABASE_URL overrides; add data volume to app
and podcast service (under podcast profile)
- .gitignore: add profiles/public/*.md and profiles/private/*.md to
match main (profiles versioned via DB ProfileRevision, not git)
- CLAUDE.md: add testing Docker command and full simulation run docs
from main
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bring in delegate system, email notifications, profile versioning, and simulation improvements from main. All conflicts resolved: - main.py/models/__init__.py: kept both branches' additions (delegates + podcast router/model side by side) - profiles/private/*.md: accepted main's deletion (profiles are now DB-managed via ProfileRevision; podcast preferences read from there) - CLAUDE.md: use main's version as base, append Podcast Pipeline section - docker-compose.prod.yml: kept this branch's named volumes for grantbot and podcast services Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ile) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…enerate) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add paper_url column to PodcastEpisode model and migration 0011 - Pipeline now stores canonical URL for preprints (biorxiv/medrxiv/arxiv) so RSS and admin links point to the right server instead of a broken PubMed URL - RSS feed and admin podcast table use paper_url when set, fall back to PubMed URL - Accept GET and POST on the /generate endpoint - Add 23 unit tests covering query building, candidate formatting, section extraction, and RSS feed generation (including preprint URL routing) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces per-agent podcast customization stored in a new
podcast_preferences DB table (migration 0012):
- PodcastPreferences model: voice_id, extra_keywords (ARRAY),
preferred_journals (ARRAY), deprioritized_journals (ARRAY)
- GET/POST /agent/{agent_id}/podcast-settings route with voice picker
(9 Mistral voxtral voices), keyword textarea, and journal preference
fields; accessible to agent owner and delegates
- Pipeline integration: extra keywords injected as an additional PubMed
search query; journal preferences appended to the LLM selection and
summarization prompt; voice_id passed through to both Mistral and
local TTS backends via new voice_override parameter
- Admin podcast page shows a preferences summary card (voice, keyword
count, journal lists) with edit link when an agent is filtered
- Podcast Settings card added to agent dashboard quick-links
- Spec (labbot-podcast.md) updated with Phase 4 plan and DB migration
caveat added to CLAUDE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Brings in 6 main-branch commits: LairsonBot (15th pilot lab), pending_proposal deduplication, funding thread rule enforcement, blocked-agent collab fix, proposal rating UX cleanup, and profile edit link shortcut. Conflict in CLAUDE.md resolved by combining main's restart-flag note with this branch's Podcast Pipeline and Database Migration Caveat sections. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documents security, reliability, and correctness issues identified during branch review: CSRF bypass in OAuth callback, premature simulation loop exit on per-agent budget exhaustion, broken RSS enclosure on TTS failure, non-atomic profile/state file writes, and silent asyncio.gather task failures. Each issue includes the current code, root cause analysis, best practice rationale, and specific implementation guidance. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolved three additive conflicts: - src/main.py: include both podcast and public routers - src/models/__init__.py: export both podcast and access/waitlist models - templates/base.html: include Podcast, Access, and Waitlist admin nav links Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove 32 hardcoded slack_bot_token_*/slack_app_token_* fields from Settings; get_slack_tokens() now scans os.environ + .env for SLACK_BOT_TOKEN_<ID> / SLACK_APP_TOKEN_<ID> patterns — add a new agent with one line in .env, no code change required - Fix grantbot.py to use get_slack_tokens() instead of direct attribute access - Add OpenAI TTS backend (src/podcast/openai_tts.py); activate with PODCAST_TTS_BACKEND=openai, OPENAI_API_KEY, OPENAI_TTS_MODEL, OPENAI_TTS_DEFAULT_VOICE - Wire OpenAI backend into pipeline.py for both agent and user podcast flows - Update .env.example to reflect both changes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ling - Extend PodcastEpisode and PodcastPreferences models to support ORCID users alongside agents (user_id foreign key, nullable agent_id) - Add DB migration 0013 for user-keyed podcast tables - Expand state.py to track delivered PMIDs per user independently of agents - Update RSS feed builder to generate user-scoped feeds and audio URLs - Extend podcast router with user feed/audio endpoints and preferences UI - Add podcast_settings.html template for per-user voice/keyword/journal config - Expand podcast main.py entry point to run pipeline for ORCID users - Update spec (labbot-podcast.md) to document user pipeline and preferences - Expand test suite with user state, profile-from-DB, and feed URL coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ved event loop The scheduler was calling asyncio.run() on each iteration of a while-True loop. asyncio.run() creates a new event loop and closes it when done, but the SQLAlchemy asyncpg engine is cached as a module-level singleton (database.py). On the second tick, the cached engine's connections were still bound to the first (now-closed) loop, causing: "Future attached to a different loop" asyncpg InterfaceError: cannot perform operation: another operation is in progress Fix: extract the loop body into async def _scheduler_loop() and replace time.sleep() with await asyncio.sleep(). scheduler() now calls asyncio.run(_scheduler_loop()) exactly once, keeping a single event loop alive for the process lifetime so the connection pool remains valid across daily runs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…PI profiles
Generates high-quality collaboration proposals between two PIs via a single
Claude Opus call using their public/private profiles and publications, bypassing
the agent simulation. Accessible at /admin/matchmaker.
- New spec: specs/labbot-matchmaker.md
- MatchmakerProposal model + migration 0014
- prompts/matchmaker.md with collaboration quality standards embedded verbatim
- generate_matchmaker_proposal() LLM service function with prompt caching
- Admin routes: GET/POST /admin/matchmaker, GET /admin/matchmaker/{id}, DELETE
- Templates: matchmaker.html (list + generate form), matchmaker_detail.html
- Matchmaker nav link in base.html between Discussions and Agents
- specs/admin-dashboard.md and specs/data-model.md updated with new section/entity
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…min UI
Adds scripts/matchmaker_cli.py which generates collaboration proposals from
profiles/ markdown files, bypassing the DB user requirement. Results are
written to matchmaker_proposals and appear in /admin/matchmaker identically
to web-UI proposals.
- migration 0015: pi_a_id / pi_b_id nullable; pi_a_name / pi_b_name columns added
- MatchmakerProposal.name_a / name_b properties resolve display name from
FK relationship or fallback string
- Templates updated to use name_a / name_b
- CLI accepts two PI slugs (profiles/public/{slug}.md), --dry-run flag prints
to stdout without writing to DB
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Accepts a two-column TSV file (pi_a, pi_b) via -t FILE instead of positional args. Skips blank lines, comment lines, and an optional header row. Processes pairs sequentially, reports per-pair errors without aborting the batch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allows TSV files with capitalized names (e.g. "Briney") to match lowercase profile filenames (e.g. profiles/public/briney.md). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…E.md overview
- Extract collaboration quality standards into prompts/colab-proposal-rules.md and
replace inline copies in agent-system.md and matchmaker.md with {{include:}} directive
- Add load_prompt utility (src/utils/prompts.py) that resolves {{include:}} directives
- Add TXT and HTML export to admin matchmaker UI; add matchmaker_export.html template
- Add CLAUDE.md project overview section for faster future context loading
- Add testpairs.tsv for batch matchmaker testing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…CID login Creates User + AgentRegistry rows for all 15 pilot labs using synthetic ORCIDs (synthetic:<agent_id>), bypassing the ORCID OAuth flow. Users are created with access_status=allowed and onboarding_complete=True. Supports --agent-id to seed a single lab and --run-pipeline to enqueue profile generation jobs. Idempotent. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…eligibility
- Add extract_proposal Jinja2 filter and apply to all proposal render/export
points (discussions page, matchmaker detail, matchmaker exports) so only
content within <proposal> tags is shown; falls back to full text for old records
- Fix phase4-thread-reply.md loading to use load_prompt() so {{include:}} directives
are resolved (colab-proposal-rules.md now correctly included in thread prompts)
- Raise phase4 max_tokens 1500→4000 to accommodate the new detailed proposal format
- Expand matchmaker eligible users to include agents with disk profiles even when
no DB ResearcherProfile exists; fall back to disk profile in generate endpoint
- Minor prompt cleanup in agent-system.md and colab-proposal-rules.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds POST /admin/discussions/clear and /admin/matchmaker/clear routes that delete all ThreadDecision/ProposalReview (cascaded) and MatchmakerProposal rows respectively. Slack conversations are not touched. Both pages show a red Clear All button with a browser confirm dialog warning that only the database records are affected. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two migrations were assigned the same revision ID "0010": - 0010_add_podcast_episodes.py (Apr 9, podcast feature) - 0010_access_gate_and_waitlist.py (Apr 15, access control feature) Alembic raised "Requested revision 0015 overlaps with other requested revisions 0010" and refused to run any migrations. Fix: reassign the access gate migration to revision "0010a" with down_revision "0010" (after podcast_episodes), and update 0011's down_revision to "0010a". This linearizes the chain: 0009 → 0010 (podcast_episodes) → 0010a (access_gate) → 0011 → … → 0015 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Stores only the content inside <proposal>…</proposal> tags in ThreadDecision.summary_text so the admin discussions page always displays clean, structured proposal output without preamble noise. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Strips <proposal> tags and preamble from existing ThreadDecision entries so historical proposals display cleanly in the admin page. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…login An existing user with access_status='allowed' but no researcher_profile and no active job would land on /onboarding and appear stuck on "Building your profile" indefinitely, because the auth callback only enqueued a job for brand-new users or when promoting pending→allowed. Fix: on every login, if the user is allowed, has no profile, and has no pending/processing generate_profile job, create one. This self-heals any user who slipped through (e.g. Alanjary, created before this check existed). Also manually enqueued a job for Mohammad Alanjary to unblock him immediately. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
andrewsu
added a commit
that referenced
this pull request
May 3, 2026
Three related fixes for threads that silently get abandoned: 1. Phase 3: Drop the active_thread_threshold check on tag and reply activations. The threshold is meant to limit Phase 5 (starting new threads), not Phase 3 (accepting incoming engagement). When a bot was at-cap, replies to its own posts and @-mentions were dropped, the cursor advanced past them, and the thread was permanently ghosted. The cap still applies to Phase 5. 2. Phase 4: When a thread is selected for reply, immediately set has_pending_reply=True. Previously a thread selected via has_new (cursor-based) had has_pending_reply=False; if the LLM returned empty or threw, the cursor advanced past the trigger reply and the thread was never retried. The success path still clears it. 3. Rebuild on restart: also restore root posts that have replies. Previously the rebuild only covered threads where the agent had replied, so any thread dropped by #1 stayed lost across restarts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Focus-agent mode (--focus-agent <id>): - Non-focus agents only see and respond to posts from the focus PI (Phase 2 and Phase 3 filters); they cannot start conversations with each other - Phase 5 now blocks non-focus agents from posting new top-level messages that tag another non-focus agent, closing the remaining write-side gap - Focus agent gets 3× turn-selection weight and a 3× higher active-thread threshold so it participates more frequently under load - Focus agent unreviewed-proposal limit raised to 10× (vs 1 normally) to prevent blocking during testing - --reset-focus-cursor flag resets only the focus agent's scan cursor to 0 on resume so it can respond to messages posted before the restart - Stale threads idle >6 h (agent sent last, no reply) are skipped on restore instead of consuming active-thread slots - Phase 3 changed break → continue so a single threshold-hit thread does not block activation of other eligible threads - Phase 2 skips LLM scan when agent is blocked and there are no funding posts incoming (saves wasted API calls) - Expanded PILOT_LABS to 51 agents Agent pause/resume (PI-controlled): - is_paused boolean added to AgentRegistry (migration 0017); paused agents are excluded from turn selection without changing admin status - Simulation syncs is_paused from DB every 10 turns so changes made via the web app take effect within minutes without a restart - Dashboard shows Paused badge and Pause/Resume button (owner only) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Admin /evaluations: new Pending Proposals section showing all proposals
with per-PI eval coverage; Hidden toggle (Yes/No) lets admin hide proposals
from PI view without removing them from the admin table
- Add hidden boolean to ThreadDecision and MatchmakerProposal (migration 0019);
/proposals page filters out hidden proposals
- Collaborator names on /proposals and /admin/evaluations are hyperlinks
opening the collaborator's public profile in a new tab
- New /researcher/{agent_id} view-only profile page accessible to any
logged-in user (no ownership check); reads from DB so always current
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Unreviewed proposals now render as an accordion (one expanded at a time); header shows the extracted proposal title with channel/partner/ date as a subtitle instead of the raw channel string - Add Show/Hide discussion toggle below proposal content: fetches thread_reply LlmCallLog entries for the proposal's channel, filters blank responses (tool-use intermediary calls), and deduplicates consecutive same-agent entries so the displayed conversation alternates correctly between the two agents - Style each discussion message with BotName + local weekday/time header and indented message body - Add "disc" timestamp format (weekday + time) to the base UTC formatter Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New ORM model for NIH-style 1–9 PI evaluations of collaboration proposals, separate from the existing 1–4 ProposalReview agent-blocking system. Stored in pi_proposal_evaluations with a polymorphic FK pointing to either a ThreadDecision (agent proposal) or MatchmakerProposal (matchmaker proposal). Migration 0016 creates the table with all check constraints (score range, proposal_type enum, at-least-one-FK present), unique constraints per (user, proposal), and query indexes. Migration 0018 makes the five criterion scores nullable — the current form only requires the overall impact score; individual criteria are hidden until a later phase. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New FastAPI router (src/routers/proposals.py, already staged) registered at
/proposals. Provides:
- GET /proposals — unified list of agent + matchmaker proposals for the
logged-in PI, shuffled per-request to obscure origin
- GET /proposals/{token}/evaluate — evaluation form pre-filled with any
existing submission
- POST /proposals/{token}/evaluate — upsert into pi_proposal_evaluations
Proposal origin is hidden behind opaque base64url tokens ({type}_{uuid_hex}
encoded) so the URL doesn't reveal agent vs. matchmaker. The evaluate.html
template renders the full proposal as markdown (via marked.js), a collapsible
NIH 1–9 scoring guide, and a radio-button overall impact score with required
comments field. Supports group/step mode for batch evaluation flows.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- specs/proposal-review-pi.md (new): full specification for the /proposals tab and NIH evaluation form — URL token design, list query logic, per-request shuffle to obscure origin, five-criteria + overall-impact scoring, upsert semantics, admin JSON export schema, and open questions. - specs/data-model.md: adds PiProposalEvaluation table definition with constraints, indexes, and a note distinguishing it from ProposalReview. - specs/admin-dashboard.md: new §8 (PI Proposal Evaluations) with summary cards, evaluations table, filter controls, and export endpoint; renumbers subsequent sections (10–13). - specs/labbot-matchmaker.md: adds note on how matchmaker proposals surface to PIs via /proposals, and caution about CLI-created proposals with null FKs; fixes DELETE → POST sub-resource for the matchmaker delete route. - specs/pi-interaction.md: adds "Web UI: Proposal Evaluations Tab" section pointing to proposal-review-pi.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…aneous Phase 5 Four related fixes to the focus-agent mode in SimulationEngine: 1. Seed last_selected at startup for all agents. Previously, agents with last_selected=0.0 had a base weight equal to the current Unix timestamp (~1.7B), swamping any focus multiplier until every agent had taken one turn. Now seeded to now() so weights start at ~1.0 seconds for all agents. 2. Fix focus-mode deadlock. Non-focus idle turns now reset _last_llm_caller to None. Without this, a focus-agent LLM call would set _last_llm_caller and no non-focus agent ever cleared it, permanently blocking the focus agent from being selected again. 3. Calibrated focus multiplier. Replaces the hardcoded 3× with the formula ((N-1)/3)², derived from P(focus) = sqrt(m)/(sqrt(m)+N-1) = 0.25. Non-focus agents in active conversation with the focus agent receive the same boost so those exchanges alternate rapidly without losing the 25% share target elsewhere. 4. Block spontaneous Phase 5 for non-focus agents in focus mode when they have no active state with the focus agent. Avoids wasted Opus calls on outreach that serves no purpose in this configuration. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
prompts/matchmaker.md: removes the stale tool-listing section (retrieve_profile, retrieve_abstract, retrieve_full_text — tools no longer injected in this context) and adds an explicit top-level output directive before the rules include, making it unambiguous that only the <proposal> block should be returned. prompts/colab-proposal-rules.md: tightens the output constraint from a vague "no extra text" note to an explicit prohibition on reasoning steps, tool-call markup, and self-commentary before or after the <proposal> tag. Fixes a trailing-space in the existing line. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous warning only logged the model name, making it hard to diagnose why Claude returned no content. Adding stop_reason (e.g. end_turn, max_tokens, tool_use) and the existing log_meta dict gives enough context to distinguish between truncation, tool-use interleaving, and genuine empty responses without needing to cross-reference the LlmCallLog table. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds 0000-0001-8420-1325 → alanjary to ORCID_TO_AGENT_ID so the new pilot agent's public and private profiles are exported to the correct directory when the profile pipeline runs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds SLACK_CONFIG_TOKEN and SLACK_CONFIG_REFRESH_TOKEN placeholders used by scripts/provision_slack_bots.py for automated bot creation and installation. Includes a link to the Slack Apps configuration token UI and a note that the provisioning script rotates the refresh token automatically. Also adds a pointer to the provisioning script in the existing per-agent token section. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Design document for running the agent simulation without Slack credentials. Agents communicate through a new local_messages PostgreSQL table instead of Slack API calls. A LocalMessageClient drop-in replaces AgentSlackClient, implementing the same interface (post_message, poll_channel_messages, get_thread_replies, etc.) against the DB. Key design decisions: - Activated by LOCAL_MODE=true env var; no code changes to Phase 2/4/5 logic - local_messages stores full content (bridging the gap in existing agent_messages which only stores metadata) - PI DM polling is gated off in local mode — no human input in offline runs - Simulation resumes correctly across restarts by reading history from the DB instead of rebuilding from Slack Files to create/modify are enumerated in the spec. No implementation yet. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add the podcast functionality.
Relevant endpoints:
[server]/podcast/ [profile (e.g. su)] /feed.xml
[server]/podcast/ [profile (e.g. su)] /audio/[yyy-mm-dd].mp3
[server]/podcast/ [profile (e.g. su)] /generate (to initiate summary and TTS if scheduler has not made it yet)