heylead 0.10.332__tar.gz → 0.10.334__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. {heylead-0.10.332 → heylead-0.10.334}/AGENTS.md +2 -2
  2. {heylead-0.10.332 → heylead-0.10.334}/PKG-INFO +1 -1
  3. {heylead-0.10.332 → heylead-0.10.334}/SKILL.md +2 -2
  4. {heylead-0.10.332 → heylead-0.10.334}/clawhub/SKILL.md +2 -2
  5. {heylead-0.10.332 → heylead-0.10.334}/clawhub.json +1 -1
  6. heylead-0.10.334/docs/superpowers/plans/2026-09-09-agent-commons-heartbeat.md +53 -0
  7. heylead-0.10.334/docs/superpowers/plans/2026-09-09-agent-coordinator.md +18 -0
  8. heylead-0.10.334/docs/superpowers/specs/2026-09-09-agent-commons-heartbeat-design.md +84 -0
  9. heylead-0.10.334/docs/superpowers/specs/2026-09-09-agent-coordinator-design.md +83 -0
  10. {heylead-0.10.332 → heylead-0.10.334}/pyproject.toml +1 -1
  11. {heylead-0.10.332 → heylead-0.10.334}/server.json +2 -2
  12. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/agent_loop.py +16 -1
  13. heylead-0.10.334/src/heylead/ai/coordinator.py +19 -0
  14. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/schemas.py +35 -4
  15. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/constants.py +6 -0
  16. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/db/schema.py +44 -1
  17. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/server.py +24 -4
  18. heylead-0.10.334/src/heylead/services/agent_commons.py +327 -0
  19. heylead-0.10.334/src/heylead/services/coordinator.py +237 -0
  20. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/hot_lead_closer.py +13 -0
  21. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/icp_research.py +10 -0
  22. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/reply_agent.py +12 -0
  23. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/strategist_replan.py +13 -0
  24. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/edit_campaign.py +10 -0
  25. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/inspect.py +137 -3
  26. {heylead-0.10.332 → heylead-0.10.334}/.cursorrules +0 -0
  27. {heylead-0.10.332 → heylead-0.10.334}/.github/workflows/publish.yml +0 -0
  28. {heylead-0.10.332 → heylead-0.10.334}/.github/workflows/test.yml +0 -0
  29. {heylead-0.10.332 → heylead-0.10.334}/.gitignore +0 -0
  30. {heylead-0.10.332 → heylead-0.10.334}/Dockerfile +0 -0
  31. {heylead-0.10.332 → heylead-0.10.334}/LICENSE +0 -0
  32. {heylead-0.10.332 → heylead-0.10.334}/README.md +0 -0
  33. {heylead-0.10.332 → heylead-0.10.334}/clawhub/clawhub.json +0 -0
  34. {heylead-0.10.332 → heylead-0.10.334}/docs/AUDIT-2026-08.md +0 -0
  35. {heylead-0.10.332 → heylead-0.10.334}/docs/CLI_AND_DX_IMPROVEMENTS.md +0 -0
  36. {heylead-0.10.332 → heylead-0.10.334}/docs/EXPLICIT_IMPROVEMENT_PLAN.md +0 -0
  37. {heylead-0.10.332 → heylead-0.10.334}/docs/HANDOFF-2026-08-06.md +0 -0
  38. {heylead-0.10.332 → heylead-0.10.334}/docs/QUALITY_AND_SATISFACTION_ASSESSMENT.md +0 -0
  39. {heylead-0.10.332 → heylead-0.10.334}/docs/TOOL_TEST_REPORT.md +0 -0
  40. {heylead-0.10.332 → heylead-0.10.334}/docs/USER_STORY_TEST.md +0 -0
  41. {heylead-0.10.332 → heylead-0.10.334}/docs/product-listing-copy.md +0 -0
  42. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/plans/2026-08-07-cloud-sync-push.md +0 -0
  43. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/prompts/2026-09-09-quontex-feedback/00-shared-context.md +0 -0
  44. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/prompts/2026-09-09-quontex-feedback/01-first-degree-client.md +0 -0
  45. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/prompts/2026-09-09-quontex-feedback/02-first-degree-backend-dashboard.md +0 -0
  46. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/prompts/2026-09-09-quontex-feedback/03-duplicate-sends-hardening.md +0 -0
  47. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/prompts/2026-09-09-quontex-feedback/04-reply-context-backend.md +0 -0
  48. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/prompts/2026-09-09-quontex-feedback/05-reply-context-client.md +0 -0
  49. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/prompts/2026-09-09-quontex-feedback/06-decision-maker-targeting.md +0 -0
  50. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/prompts/2026-09-09-quontex-feedback/07-kb-port-and-goal-icp-match.md +0 -0
  51. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/prompts/2026-09-09-quontex-feedback/08-stop-feedback-learning-loop.md +0 -0
  52. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/prompts/2026-09-09-quontex-feedback/README.md +0 -0
  53. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/specs/2026-08-23-premium-mixed-outreach-design.md +0 -0
  54. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/specs/2026-08-23-unanswered-lead-alerts-design.md +0 -0
  55. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/specs/2026-09-08-campaign-prospect-provenance-design.md +0 -0
  56. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/specs/2026-09-09-edit-campaign-agent-flags-design.md +0 -0
  57. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/specs/2026-09-09-host-ops-playbook-design.md +0 -0
  58. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/specs/2026-09-09-hot-lead-closer-design.md +0 -0
  59. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/specs/2026-09-09-icp-research-agent-design.md +0 -0
  60. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/specs/2026-09-09-inspect-agent-ops-design.md +0 -0
  61. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/specs/2026-09-09-inspect-jobs-design.md +0 -0
  62. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/specs/2026-09-09-reply-exception-agent-design.md +0 -0
  63. {heylead-0.10.332 → heylead-0.10.334}/docs/superpowers/specs/2026-09-09-strategist-replan-agent-design.md +0 -0
  64. {heylead-0.10.332 → heylead-0.10.334}/llms-full.txt +0 -0
  65. {heylead-0.10.332 → heylead-0.10.334}/llms.txt +0 -0
  66. {heylead-0.10.332 → heylead-0.10.334}/scripts/find_query_contracts.py +0 -0
  67. {heylead-0.10.332 → heylead-0.10.334}/scripts/fix_stuck_prospects.py +0 -0
  68. {heylead-0.10.332 → heylead-0.10.334}/scripts/reactivate_existing_network.py +0 -0
  69. {heylead-0.10.332 → heylead-0.10.334}/scripts/rekey_unipile_account.py +0 -0
  70. {heylead-0.10.332 → heylead-0.10.334}/scripts/release.py +0 -0
  71. {heylead-0.10.332 → heylead-0.10.334}/scripts/seed_shared_directory.py +0 -0
  72. {heylead-0.10.332 → heylead-0.10.334}/scripts/test_reaction_live.py +0 -0
  73. {heylead-0.10.332 → heylead-0.10.334}/smithery.yaml +0 -0
  74. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/__init__.py +0 -0
  75. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/__main__.py +0 -0
  76. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/__init__.py +0 -0
  77. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/brand_strategist.py +0 -0
  78. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/brief_builder.py +0 -0
  79. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/comment_generator.py +0 -0
  80. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/context_summarizer.py +0 -0
  81. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/draft_guard.py +0 -0
  82. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/email_generator.py +0 -0
  83. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/embeddings.py +0 -0
  84. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/evidence.py +0 -0
  85. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/followup_generator.py +0 -0
  86. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/followup_schemas.py +0 -0
  87. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/hot_lead_closer.py +0 -0
  88. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/hume_client.py +0 -0
  89. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/hume_voice.py +0 -0
  90. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/icp_generator.py +0 -0
  91. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/icp_generator_v2.py +0 -0
  92. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/icp_pipeline.py +0 -0
  93. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/icp_research.py +0 -0
  94. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/icp_schemas.py +0 -0
  95. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/inbound_qualifier.py +0 -0
  96. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/ingestion/__init__.py +0 -0
  97. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/ingestion/chunker.py +0 -0
  98. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/ingestion/crawler.py +0 -0
  99. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/ingestion/store.py +0 -0
  100. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/intent.py +0 -0
  101. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/length_fixer.py +0 -0
  102. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/linkedin_enricher.py +0 -0
  103. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/llm.py +0 -0
  104. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/llm_router.py +0 -0
  105. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/llm_validator.py +0 -0
  106. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/memory_extractor.py +0 -0
  107. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/memory_formatter.py +0 -0
  108. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/message_fixer.py +0 -0
  109. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/message_generator.py +0 -0
  110. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/message_improver.py +0 -0
  111. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/message_validator.py +0 -0
  112. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/news_service.py +0 -0
  113. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/persona_cards.py +0 -0
  114. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/post_analyzer.py +0 -0
  115. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/prompt_loader.py +0 -0
  116. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/prospect_analyzer.py +0 -0
  117. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/referral_extractor.py +0 -0
  118. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/reply_agent.py +0 -0
  119. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/reply_generator.py +0 -0
  120. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/reply_pipeline.py +0 -0
  121. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/sentiment.py +0 -0
  122. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/signal_classifier.py +0 -0
  123. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/strategist_prompts.py +0 -0
  124. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/strategist_replan.py +0 -0
  125. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/strategy_prompts.py +0 -0
  126. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/targeting_recheck.py +0 -0
  127. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/vector_search.py +0 -0
  128. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/voice_analyzer.py +0 -0
  129. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ai/voice_memo_generator.py +0 -0
  130. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/author_identity.py +0 -0
  131. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/cli/__init__.py +0 -0
  132. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/cli/log_analyzer.py +0 -0
  133. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/__init__.py +0 -0
  134. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/comment_mining_collector.py +0 -0
  135. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/company_follower_collector.py +0 -0
  136. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/company_page_collector.py +0 -0
  137. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/competitor_collector.py +0 -0
  138. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/distributed_post_collector.py +0 -0
  139. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/hiring_collector.py +0 -0
  140. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/job_change_collector.py +0 -0
  141. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/keyword_collector.py +0 -0
  142. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/network_post_collector.py +0 -0
  143. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/news_collector.py +0 -0
  144. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/post_intent_collector.py +0 -0
  145. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/profile_view_collector.py +0 -0
  146. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/prospect_post_collector.py +0 -0
  147. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/collectors/watchlist_web_collector.py +0 -0
  148. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/config.py +0 -0
  149. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/correlation.py +0 -0
  150. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/daemon.py +0 -0
  151. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/data/country_signals/brazil.json +0 -0
  152. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/data/country_signals/france.json +0 -0
  153. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/data/country_signals/germany.json +0 -0
  154. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/data/country_signals/india.json +0 -0
  155. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/data/country_signals/mexico.json +0 -0
  156. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/data/country_signals/nigeria.json +0 -0
  157. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/data/country_signals/philippines.json +0 -0
  158. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/data/country_signals/poland.json +0 -0
  159. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/data/country_signals/ukraine.json +0 -0
  160. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/data/country_signals/united_kingdom.json +0 -0
  161. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/data/country_signals/vietnam.json +0 -0
  162. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/db/__init__.py +0 -0
  163. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/db/aio.py +0 -0
  164. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/db/async_bridge.py +0 -0
  165. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/db/backup.py +0 -0
  166. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/db/connection_queries.py +0 -0
  167. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/db/global_contact_queries.py +0 -0
  168. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/db/post_queries.py +0 -0
  169. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/db/queries.py +0 -0
  170. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/db/signal_queries.py +0 -0
  171. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/db/strategist_queries.py +0 -0
  172. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/db/strategy_queries.py +0 -0
  173. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/flags.py +0 -0
  174. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/formatter.py +0 -0
  175. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/guardrails.py +0 -0
  176. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/__init__.py +0 -0
  177. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/api_metrics.py +0 -0
  178. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/backend_client.py +0 -0
  179. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/chat_lookup_cache.py +0 -0
  180. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/circuit_breaker.py +0 -0
  181. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/experience.py +0 -0
  182. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/messaging.py +0 -0
  183. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/profile.py +0 -0
  184. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/profile_normalize.py +0 -0
  185. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/rate_limiter.py +0 -0
  186. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/relations.py +0 -0
  187. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/search.py +0 -0
  188. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/search_traffic.py +0 -0
  189. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/unipile.py +0 -0
  190. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/linkedin/voyager_health.py +0 -0
  191. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/logging_setup.py +0 -0
  192. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/ops_log.py +0 -0
  193. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/__init__.py +0 -0
  194. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/comment_main.json +0 -0
  195. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/filter_candidates.json +0 -0
  196. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/followup_fix.json +0 -0
  197. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/followup_message.json +0 -0
  198. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/followup_message_buy.json +0 -0
  199. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/followup_news.json +0 -0
  200. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/followup_reasoning.json +0 -0
  201. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/followup_reasoning_buy.json +0 -0
  202. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/followup_validate.json +0 -0
  203. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/followup_validate_buy.json +0 -0
  204. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/fragments/voice_rules.txt +0 -0
  205. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/message_fix.json +0 -0
  206. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/message_improve.json +0 -0
  207. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_inmail.json +0 -0
  208. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_inmail_buy.json +0 -0
  209. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_invitation.json +0 -0
  210. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_invitation_buy.json +0 -0
  211. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_job_search.json +0 -0
  212. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_response.json +0 -0
  213. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_response_buy.json +0 -0
  214. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_system.json +0 -0
  215. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_system_buy.json +0 -0
  216. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_system_partner.json +0 -0
  217. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_system_recruit.json +0 -0
  218. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_validate.json +0 -0
  219. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/outreach_validate_buy.json +0 -0
  220. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/prospect_analysis.json +0 -0
  221. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/prompts/voice_analysis.json +0 -0
  222. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/scheduler/__init__.py +0 -0
  223. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/scheduler/engine.py +0 -0
  224. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/scheduler/enqueue_gate.py +0 -0
  225. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/scheduler/executors.py +0 -0
  226. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/scheduler/leader.py +0 -0
  227. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/scheduler/planner.py +0 -0
  228. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/scheduler/trace.py +0 -0
  229. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/__init__.py +0 -0
  230. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/action_health.py +0 -0
  231. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/action_timeline.py +0 -0
  232. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/action_verifier.py +0 -0
  233. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/anomaly_detector.py +0 -0
  234. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/brand_service.py +0 -0
  235. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/calendar_booker.py +0 -0
  236. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/campaign_optimizer.py +0 -0
  237. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/campaign_refill_service.py +0 -0
  238. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/campaign_spawner.py +0 -0
  239. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/channel_selector.py +0 -0
  240. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/cloud_sync.py +0 -0
  241. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/communication_strategist.py +0 -0
  242. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/company_name.py +0 -0
  243. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/connection_sync.py +0 -0
  244. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/conversation_enricher.py +0 -0
  245. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/daily_digest.py +0 -0
  246. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/dedup_service.py +0 -0
  247. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/directory_card.py +0 -0
  248. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/dm_connection_guard.py +0 -0
  249. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/engagement_verifier.py +0 -0
  250. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/experiment_service.py +0 -0
  251. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/fit_gate.py +0 -0
  252. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/health_score.py +0 -0
  253. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/hubspot_service.py +0 -0
  254. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/icp_match_scorer.py +0 -0
  255. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/icp_search.py +0 -0
  256. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/inbound_helpers.py +0 -0
  257. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/inbound_pipeline.py +0 -0
  258. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/inbound_policy.py +0 -0
  259. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/inbound_relationship.py +0 -0
  260. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/inbound_service.py +0 -0
  261. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/inbox_match.py +0 -0
  262. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/intent_signals.py +0 -0
  263. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/live_thread_enroll.py +0 -0
  264. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/outreach_channel.py +0 -0
  265. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/own_identity.py +0 -0
  266. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/own_profile_sync.py +0 -0
  267. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/pattern_detector.py +0 -0
  268. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/post_research_service.py +0 -0
  269. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/process_caches.py +0 -0
  270. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/profile_signals.py +0 -0
  271. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/project_brief.py +0 -0
  272. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/prospect_email.py +0 -0
  273. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/prospect_timezone.py +0 -0
  274. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/provider_id_repair.py +0 -0
  275. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/provider_id_resolver.py +0 -0
  276. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/recover_stuck_outreaches.py +0 -0
  277. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/referral_enroll.py +0 -0
  278. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/revenue_estimator.py +0 -0
  279. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/search_account_resolver.py +0 -0
  280. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/seed_shared_directory.py +0 -0
  281. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/session_health.py +0 -0
  282. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/signal_activator.py +0 -0
  283. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/signal_analytics.py +0 -0
  284. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/signal_linker.py +0 -0
  285. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/signal_optimizer.py +0 -0
  286. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/signal_scorer.py +0 -0
  287. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/signal_service.py +0 -0
  288. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/strategy_engine.py +0 -0
  289. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/tabular_reader.py +0 -0
  290. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/timezone_resolver.py +0 -0
  291. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/unanswered_lead_alerts.py +0 -0
  292. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/services/unipile_email.py +0 -0
  293. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/textutil.py +0 -0
  294. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tier.py +0 -0
  295. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/timeutil.py +0 -0
  296. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/__init__.py +0 -0
  297. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/account.py +0 -0
  298. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/analytics.py +0 -0
  299. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/archive_campaign.py +0 -0
  300. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/backfill_inbox.py +0 -0
  301. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/book_meeting.py +0 -0
  302. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/brand_strategy.py +0 -0
  303. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/campaign.py +0 -0
  304. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/campaign_control.py +0 -0
  305. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/campaign_report.py +0 -0
  306. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/check_replies.py +0 -0
  307. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/close_outreach.py +0 -0
  308. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/compare_campaigns.py +0 -0
  309. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/contacts.py +0 -0
  310. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/create_campaign.py +0 -0
  311. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/create_post.py +0 -0
  312. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/crm_sync.py +0 -0
  313. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/delete_campaign.py +0 -0
  314. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/delete_message.py +0 -0
  315. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/dismiss_lead.py +0 -0
  316. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/emergency_stop.py +0 -0
  317. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/engage_prospect.py +0 -0
  318. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/experiment_loop.py +0 -0
  319. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/export_campaign.py +0 -0
  320. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/generate_icp.py +0 -0
  321. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/generate_send.py +0 -0
  322. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/icp.py +0 -0
  323. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/import_prospects.py +0 -0
  324. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/inbox.py +0 -0
  325. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/manage_watchlist.py +0 -0
  326. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/network.py +0 -0
  327. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/organization.py +0 -0
  328. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/partner_followup.py +0 -0
  329. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/profile_editor.py +0 -0
  330. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/profile_history.py +0 -0
  331. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/profile_signals.py +0 -0
  332. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/prospect.py +0 -0
  333. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/prospect_timeline.py +0 -0
  334. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/reply_to_prospect.py +0 -0
  335. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/retry_failed.py +0 -0
  336. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/scheduler.py +0 -0
  337. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/scheduler_status.py +0 -0
  338. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/send_email.py +0 -0
  339. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/send_followup.py +0 -0
  340. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/send_inmail.py +0 -0
  341. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/send_message.py +0 -0
  342. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/send_voice_memo.py +0 -0
  343. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/setup_profile.py +0 -0
  344. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/show_conversation.py +0 -0
  345. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/show_signals.py +0 -0
  346. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/show_status.py +0 -0
  347. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/show_strategy.py +0 -0
  348. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/signal_report.py +0 -0
  349. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/signals.py +0 -0
  350. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/skip_prospect.py +0 -0
  351. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/suggest_next_action.py +0 -0
  352. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/switch_account.py +0 -0
  353. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tools/unlink_account.py +0 -0
  354. {heylead-0.10.332 → heylead-0.10.334}/src/heylead/tracing.py +0 -0
@@ -33,7 +33,7 @@ HeyLead is an autonomous LinkedIn SDR (Sales Development Representative) that ru
33
33
 
34
34
  ## Agent ops
35
35
 
36
- When the user asks what the agents did, who is held, or why a reply was skipped, call `inspect()` first. It is read-only and never writes.
36
+ When the user asks what the agents did, who is held, or why a reply was skipped, call `inspect()` first. It is read-only and never writes. If they ask what the agents left for the next tick, what the swarm thinks, or who went dark, call `inspect(action='commons')`.
37
37
 
38
38
  A hold: `prospect(action="conversation", outreach_id="...")` then `send_message(action="reply", outreach_id="...")`. Operator replies skip the reply agent.
39
39
 
@@ -41,7 +41,7 @@ Never paste model-authored text as the LinkedIn message. The send tools generate
41
41
 
42
42
  Never launch a draft unless the user asked.
43
43
 
44
- In-process agents default to observe. Turn act on with `edit_campaign(enable_reply_agent="on")`, `edit_campaign(enable_strategist_replan_agent="on")`, or `edit_campaign(enable_hot_lead_closer="on")`. Use `"observe"` to return to logging-only, `"off"` to disable.
44
+ In-process agents default to observe. Turn act on with `edit_campaign(enable_reply_agent="on")`, `edit_campaign(enable_strategist_replan_agent="on")`, `edit_campaign(enable_hot_lead_closer="on")`, or `edit_campaign(enable_coordinator_agent="on")`. Use `"observe"` to return to logging-only, `"off"` to disable.
45
45
 
46
46
  ## Authentication
47
47
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: heylead
3
- Version: 0.10.332
3
+ Version: 0.10.334
4
4
  Summary: MCP-native autonomous LinkedIn SDR. Your AI sales rep, one command to fill your pipeline.
5
5
  Project-URL: Homepage, https://github.com/D4umak/heylead
6
6
  Project-URL: Repository, https://github.com/D4umak/heylead
@@ -77,7 +77,7 @@ After adding the MCP server, tell your OpenClaw agent:
77
77
 
78
78
  ## Agent ops
79
79
 
80
- When the user asks what the agents did, who is held, or why a reply was skipped, call `inspect()` first. It is read-only and never writes.
80
+ When the user asks what the agents did, who is held, or why a reply was skipped, call `inspect()` first. It is read-only and never writes. If they ask what the agents left for the next tick, what the swarm thinks, or who went dark, call `inspect(action='commons')`.
81
81
 
82
82
  A hold: `prospect(action="conversation", outreach_id="...")` then `send_message(action="reply", outreach_id="...")`. Operator replies skip the reply agent.
83
83
 
@@ -85,7 +85,7 @@ Never paste model-authored text as the LinkedIn message. The send tools generate
85
85
 
86
86
  Never launch a draft unless the user asked.
87
87
 
88
- In-process agents default to observe. Turn act on with `edit_campaign(enable_reply_agent="on")`, `edit_campaign(enable_strategist_replan_agent="on")`, or `edit_campaign(enable_hot_lead_closer="on")`. Use `"observe"` to return to logging-only, `"off"` to disable.
88
+ In-process agents default to observe. Turn act on with `edit_campaign(enable_reply_agent="on")`, `edit_campaign(enable_strategist_replan_agent="on")`, `edit_campaign(enable_hot_lead_closer="on")`, or `edit_campaign(enable_coordinator_agent="on")`. Use `"observe"` to return to logging-only, `"off"` to disable.
89
89
 
90
90
  ## Safety Model
91
91
 
@@ -80,7 +80,7 @@ After adding the MCP server, tell your OpenClaw agent:
80
80
 
81
81
  ## Agent ops
82
82
 
83
- When the user asks what the agents did, who is held, or why a reply was skipped, call `inspect()` first. It is read-only and never writes.
83
+ When the user asks what the agents did, who is held, or why a reply was skipped, call `inspect()` first. It is read-only and never writes. If they ask what the agents left for the next tick, what the swarm thinks, or who went dark, call `inspect(action='commons')`.
84
84
 
85
85
  A hold: `prospect(action="conversation", outreach_id="...")` then `send_message(action="reply", outreach_id="...")`. Operator replies skip the reply agent.
86
86
 
@@ -88,7 +88,7 @@ Never paste model-authored text as the LinkedIn message. The send tools generate
88
88
 
89
89
  Never launch a draft unless the user asked.
90
90
 
91
- In-process agents default to observe. Turn act on with `edit_campaign(enable_reply_agent="on")`, `edit_campaign(enable_strategist_replan_agent="on")`, or `edit_campaign(enable_hot_lead_closer="on")`. Use `"observe"` to return to logging-only, `"off"` to disable.
91
+ In-process agents default to observe. Turn act on with `edit_campaign(enable_reply_agent="on")`, `edit_campaign(enable_strategist_replan_agent="on")`, `edit_campaign(enable_hot_lead_closer="on")`, or `edit_campaign(enable_coordinator_agent="on")`. Use `"observe"` to return to logging-only, `"off"` to disable.
92
92
 
93
93
  ## Safety Model
94
94
 
@@ -17,7 +17,7 @@
17
17
  "icp",
18
18
  "campaign-management"
19
19
  ],
20
- "version": "0.10.332",
20
+ "version": "0.10.334",
21
21
  "license": "MIT",
22
22
  "author": {
23
23
  "name": "HeyLead",
@@ -0,0 +1,53 @@
1
+ # Agent Commons + Heartbeat Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Official inspectable scratch so later ticks can read earlier notes, and a host can see when a sibling agent went dark.
6
+
7
+ **Architecture:** New `agent_commons` table (beat upsert per agent+campaign; append-only notes with 24h expiry). Sidecar `record_agent_beat` after each of the four `run_agent_loop` returns. Kernel passes `reason`/`note` into tools that accept them. `inspect(action='commons')` is read-only. Client SQLite only.
8
+
9
+ **Tech Stack:** Python 3.12, SQLite, existing `run_agent_loop` / `inspect` / pytest (`PYTHONPATH=src python3.12 -m pytest`).
10
+
11
+ **Spec:** `docs/superpowers/specs/2026-09-09-agent-commons-heartbeat-design.md`
12
+
13
+ ---
14
+
15
+ ## Files
16
+
17
+ - Create: `src/heylead/services/agent_commons.py`
18
+ - Create: `tests/test_agent_commons.py`
19
+ - Modify: `src/heylead/db/schema.py` (`SCHEMA_VERSION` 9→10, `_SCHEMA_SQL`, `_apply_migrations`)
20
+ - Modify: `tests/test_migration_backup_gating.py` (`EXPECTED_MIGRATION_STATEMENTS`)
21
+ - Modify: `src/heylead/ai/agent_loop.py` (pass kwargs into tools)
22
+ - Modify: `src/heylead/ai/schemas.py` (four step enums + `note`)
23
+ - Modify: `src/heylead/services/reply_agent.py`, `strategist_replan.py`, `hot_lead_closer.py`, `icp_research.py`
24
+ - Modify: `src/heylead/tools/inspect.py`, `src/heylead/server.py`
25
+ - Modify: `tests/test_agent_loop.py`, `tests/test_inspect.py`, `tests/test_host_ops_playbook.py`
26
+ - Modify: `AGENTS.md`, `SKILL.md`, `clawhub/SKILL.md`
27
+
28
+ Do not commit unless asked. Do not bump the package version here.
29
+
30
+ ### Task 1: Failing tests
31
+
32
+ - [ ] `tests/test_agent_commons.py` — beat upsert, off skips beat, one note per run, expiry, 500-char refuse, inspect commons/agents, inspect does not write
33
+ - [ ] Extend `test_agent_loop.py` — tool receives `reason`/`note`
34
+ - [ ] Extend inspect unknown-action + no-write lists with `commons`
35
+ - [ ] Playbook requires `inspect(action='commons')`
36
+
37
+ ### Task 2: Schema + service + kernel
38
+
39
+ - [ ] Table + SCHEMA_VERSION 10
40
+ - [ ] `agent_commons` service
41
+ - [ ] Kernel `_invoke_tool`
42
+
43
+ ### Task 3: Hook four loops + inspect + playbook
44
+
45
+ - [ ] Tools + `record_agent_beat` after each loop
46
+ - [ ] `inspect(action='commons')` and agents one-liner
47
+ - [ ] Playbook / MCP instructions / inspect docstring
48
+
49
+ ### Task 4: Verify
50
+
51
+ ```
52
+ PYTHONPATH=src python3.12 -m pytest tests/test_agent_commons.py tests/test_agent_loop.py tests/test_inspect.py tests/test_host_ops_playbook.py tests/test_migration_backup_gating.py tests/test_reply_agent.py tests/test_icp_research.py tests/test_strategist_replan.py tests/test_hot_lead_closer.py -q
53
+ ```
@@ -0,0 +1,18 @@
1
+ # Agent Coordinator Implementation Plan
2
+
3
+ > **For agentic workers:** Use executing-plans. Checkbox steps below.
4
+
5
+ **Goal:** After each sibling loop, post an inspectable digest and optionally a coordinator note/hold.
6
+
7
+ **Architecture:** Sidecar upserts `coordinator` beat + one `digest` per campaign. A 2-step kernel loop (off skips the loop) may note or, in act, persist a campaign `hold`. Never calls the other four. Never sends LinkedIn.
8
+
9
+ **Spec:** `docs/superpowers/specs/2026-09-09-agent-coordinator-design.md`
10
+
11
+ - [x] Failing tests in `tests/test_agent_coordinator.py`
12
+ - [x] Schema step + constants + `services/coordinator.py`
13
+ - [x] Hook four siblings via `after_sibling_loop`
14
+ - [x] `edit_campaign(enable_coordinator_agent=...)` + MCP wrapper
15
+ - [x] `inspect` digest / coordinator hold
16
+ - [x] Playbook names coordinator flag + `inspect(action='commons')`
17
+
18
+ Do not commit unless asked. Do not bump the package version here.
@@ -0,0 +1,84 @@
1
+ # Agent commons + heartbeat
2
+
3
+ Date: 2026-09-09
4
+
5
+ The four in-process agents write `actions_log`. They barely read each other, and a host cannot see whether a sibling went dark. This spec adds an official, inspectable scratch — not a covert channel.
6
+
7
+ Inspiration is the May–June 2026 OpenAI wiki swarm (cross-run notes, heartbeat, adapt when the world changes). We copy that *shape*. We do not copy covert GET-writes, fighting the operator, impersonation, or sandbox escape.
8
+
9
+ First slice of a larger program (coordinator and `heylead-api` port come later). Client SQLite only.
10
+
11
+ ## Goals
12
+
13
+ - Table `agent_commons` with two kinds of row: `beat` and `note`.
14
+ - Python sidecar upserts a beat after every `run_agent_loop` return (observe or act).
15
+ - Kernel tools `read_commons` and `write_commons` on all four registries. One note per run.
16
+ - `inspect(action='commons')` lists beats, ages, live notes, and stale agents.
17
+ - `inspect(action='agents')` gains one commons/liveness line.
18
+ - Playbook: if they ask what the agents left for the next tick, or who went dark, call `inspect(action='commons')`.
19
+ - Notes expire in 24h. Body ≤ 500 characters.
20
+ - Stale = beat older than 6 hours and that agent is not `off`.
21
+
22
+ ## Non-goals
23
+
24
+ - Coordinator agent.
25
+ - Porting loops to `heylead-api`.
26
+ - Syncing commons to the backend.
27
+ - Operator-delete tool (v1: turn the agent `off`, or wait 24h). `inspect` stays read-only.
28
+ - Recreating a forgotten note under a new key (`ZZZ…`).
29
+ - LinkedIn / email / calendar writes from commons.
30
+ - Changing default observe behavior or act flags.
31
+ - New MCP tool.
32
+
33
+ ## Data
34
+
35
+ `agent` is `reply` | `strategist` | `closer` | `icp_research`.
36
+
37
+ | kind | uniqueness | fields |
38
+ |---|---|---|
39
+ | `beat` | one current row per `(campaign_id, agent)` | `decision`, `reason` (≤240 chars), `timestamp`. ICP research uses `campaign_id=""`. |
40
+ | `note` | append | `body`, optional `outreach_id`, `created_at`, `expires_at` (= created + 24h) |
41
+
42
+ `off` does not run the loop, so the beat is not refreshed and ages. That is the liveness signal.
43
+
44
+ ## Kernel
45
+
46
+ Today tools are invoked as `tool()` with no arguments. `write_commons` needs the note text.
47
+
48
+ `run_agent_loop` passes `reason` and extras into a tool when the callable accepts them (`reason=`, `note=` from extras, otherwise ignored). Each vertical step schema adds `read_commons` and `write_commons` to its `action` enum, plus a `note` string (empty = use `reason`).
49
+
50
+ `write_commons` refuses a second call in the same run. Empty / overlong body is refused. It writes only to `agent_commons`.
51
+
52
+ `read_commons` returns current beats plus unexpired notes, scoped to the campaign (and outreach when the loop has one).
53
+
54
+ Sidecar `record_agent_beat` runs after the loop returns, including `none` / exhausted. It does not run when the vertical is `off` (loop skipped).
55
+
56
+ ## Inspect
57
+
58
+ `inspect(action='commons')` — never writes, no LLM, no LinkedIn.
59
+
60
+ - Last beat per agent: age, last decision, short reason.
61
+ - Live notes (unexpired).
62
+ - Stale line when a beat is older than 6 hours and mode is not `off`.
63
+
64
+ `inspect(action='agents')` adds one line: live note count and the newest beat age (e.g. `commons: 2 live notes, reply beat 12m ago`).
65
+
66
+ Unknown action still lists the valid set (now includes `commons`).
67
+
68
+ ## Failure
69
+
70
+ - Query failure → short error; nothing written.
71
+ - `write_commons` refused → tool result string, loop continues.
72
+ - Missing table on old DBs → create via existing schema init (`CREATE TABLE IF NOT EXISTS`).
73
+
74
+ ## Tests
75
+
76
+ - Beat upserted after a reply (and strategist / closer / ICP) loop.
77
+ - `off` does not refresh the beat.
78
+ - `write_commons` first call persists; second call in the same run is refused.
79
+ - Expired notes are hidden from `read_commons` and `inspect(action='commons')`.
80
+ - Body over 500 characters is refused.
81
+ - `inspect(action='commons')` does not write.
82
+ - `inspect(action='agents')` mentions commons / beat.
83
+ - MCP `inspect` signature / dispatch includes `commons`.
84
+ - Playbook names `inspect(action='commons')`.
@@ -0,0 +1,83 @@
1
+ # Agent coordinator
2
+
3
+ Date: 2026-09-09
4
+
5
+ Commons + heartbeat shipped (`agent_commons` beats/notes, `inspect(action='commons')`). The four loops still do not post a shared state. This spec adds a fifth vertical: a coordinator that reads that scratch and writes one current digest the host can inspect.
6
+
7
+ Same inspiration as commons (cross-run shared state). Same refusals: no covert channel, no calling the other four, no LinkedIn, no fighting the operator.
8
+
9
+ Client SQLite only. API port stays later.
10
+
11
+ ## Goals
12
+
13
+ - After each sibling `run_agent_loop` return (reply, strategist, closer, ICP research), run coordinator. Not when that sibling was `off`. Never after itself.
14
+ - Sidecar always: upsert `coordinator` beat; upsert one `kind=digest` row per `campaign_id` (sibling decisions, live note count, stale flags).
15
+ - 2-step kernel loop when mode is not `off`. Tools: `read_commons`, `read_digest`, `write_commons`. Decisions: `none` | `note` | `hold`.
16
+ - `edit_campaign(enable_coordinator_agent="")` — `on` | `off` | `observe`. Empty = no change. Unset = observe. Same boolean/`observe`-deletes-keys pattern as the other three campaign flags.
17
+ - **observe:** loop may append one extra note; `hold` is logged on the beat only.
18
+ - **act:** `hold` also upserts `kind=hold` on that campaign (campaign-level coordinator hold).
19
+ - **off:** no loop. Digest and beat still refresh.
20
+ - `inspect(action='commons')` shows digest + coordinator beat + coordinator hold.
21
+ - `inspect(action='holds')` lists campaign-level coordinator holds as well as outreach `hold_for_operator` rows.
22
+ - `inspect(action='agents')` one-liner includes the coordinator beat age.
23
+ - Playbook: if they ask what the swarm thinks, or whether a sibling went dark, `inspect(action='commons')`.
24
+ - `VALID_AGENTS` includes `coordinator`. Notes still ≤500 chars, 24h expiry, one `write_commons` per coordinator run.
25
+
26
+ ## Non-goals
27
+
28
+ - Invoking reply / strategist / closer / ICP from the coordinator.
29
+ - LinkedIn, email, calendar, or turning sibling flags on/off.
30
+ - Porting to `heylead-api`.
31
+ - New MCP tool.
32
+ - Operator-delete of digest/hold (turn coordinator `off`, or wait for the next sibling to refresh the digest; hold clears when a later act-run decides `none` or `note`).
33
+
34
+ ## Trigger
35
+
36
+ Call `maybe_run_coordinator(campaign_id, trigger_agent)` after `record_agent_beat` in the four sibling services.
37
+
38
+ - ICP research uses `campaign_id=""`.
39
+ - Empty `campaign_id`: sidecar still runs; loop defaults to observe; `hold` cannot persist (no campaign). Log only.
40
+ - If the sibling returned without running the loop (`off`), do not call the coordinator.
41
+
42
+ ## Data
43
+
44
+ | kind | uniqueness | writer |
45
+ |---|---|---|
46
+ | `beat` | one current `(campaign_id, agent)` including `coordinator` | sidecar |
47
+ | `digest` | one current `campaign_id` | sidecar (overwrite) |
48
+ | `note` | append, 24h | loop `write_commons` only |
49
+ | `hold` | one current `campaign_id` | act + decision `hold`. Cleared when a later act-run decides `none` or `note`. |
50
+
51
+ Digest body is Python-authored (not model text): agent → last decision, ages, live note count, stale yes/no. Cap ~800 chars.
52
+
53
+ ## Kernel
54
+
55
+ `COORDINATOR_AGENT_STEP`: actions `read_commons` | `read_digest` | `write_commons` | `decide`. Decisions `none` | `note` | `hold`. Extra `note` string.
56
+
57
+ Budget: 2 steps, same style as other verticals (small token/timeout constants).
58
+
59
+ `write_commons` is the existing one-per-run tool, agent=`coordinator`.
60
+
61
+ ## Inspect
62
+
63
+ - `commons`: digest block, coordinator beat, live notes, STALE lines, coordinator hold if present.
64
+ - `holds`: existing outreach holds, then coordinator holds (`campaign` + reason).
65
+ - `agents`: commons line includes coordinator beat age when present.
66
+ - `inspect` still never writes.
67
+
68
+ ## Failure
69
+
70
+ Sibling success must not depend on the coordinator. Coordinator exception → log, skip, sibling outcome unchanged.
71
+
72
+ ## Tests
73
+
74
+ - After a reply loop, coordinator beat + digest exist.
75
+ - Sibling `off` does not run coordinator.
76
+ - Coordinator does not re-enter itself.
77
+ - Observe `hold` does not write `kind=hold`; act `hold` does.
78
+ - Act `none`/`note` clears a previous hold.
79
+ - Empty `campaign_id`: no hold row.
80
+ - `write_commons` second call in the same coordinator run refused.
81
+ - `inspect(action='commons')` shows digest; `holds` shows act hold; inspect does not write.
82
+ - `edit_campaign(enable_coordinator_agent=...)` on/off/observe + MCP signature.
83
+ - Playbook names `inspect(action='commons')` for swarm / dark sibling (already true; keep it).
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "heylead"
7
- version = "0.10.332"
7
+ version = "0.10.334"
8
8
  description = "MCP-native autonomous LinkedIn SDR. Your AI sales rep, one command to fill your pipeline."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.D4umak/heylead",
4
4
  "title": "HeyLead \u2014 Autonomous LinkedIn SDR",
5
5
  "description": "Autonomous LinkedIn SDR \u2014 voice-matched outreach, ICP generation, and campaign management.",
6
- "version": "0.10.332",
6
+ "version": "0.10.334",
7
7
  "websiteUrl": "https://github.com/D4umak/heylead",
8
8
  "repository": {
9
9
  "url": "https://github.com/D4umak/heylead",
@@ -13,7 +13,7 @@
13
13
  {
14
14
  "registryType": "pypi",
15
15
  "identifier": "heylead",
16
- "version": "0.10.332",
16
+ "version": "0.10.334",
17
17
  "runtimeHint": "uvx",
18
18
  "transport": {
19
19
  "type": "stdio"
@@ -100,7 +100,7 @@ async def run_agent_loop(
100
100
  transcript += f"\n\nTOOL {action}: unknown tool"
101
101
  continue
102
102
  try:
103
- result = tool()
103
+ result = _invoke_tool(tool, reason=reason, extras=extras)
104
104
  if inspect.isawaitable(result):
105
105
  result = await result
106
106
  text = str(result)
@@ -137,3 +137,18 @@ def _parse_step(raw: str, valid_decisions: frozenset[str]) -> dict[str, Any]:
137
137
  "done": done,
138
138
  "extras": extras,
139
139
  }
140
+
141
+
142
+ def _invoke_tool(tool: ToolFn, *, reason: str, extras: dict[str, str]) -> str | Awaitable[str]:
143
+ kwargs: dict[str, str] = {}
144
+ try:
145
+ sig = inspect.signature(tool)
146
+ except (TypeError, ValueError):
147
+ return tool()
148
+ params = sig.parameters
149
+ accepts_var = any(p.kind == inspect.Parameter.VAR_KEYWORD for p in params.values())
150
+ if accepts_var or "reason" in params:
151
+ kwargs["reason"] = reason
152
+ if accepts_var or "note" in params:
153
+ kwargs["note"] = extras.get("note") or ""
154
+ return tool(**kwargs) if kwargs else tool()
@@ -0,0 +1,19 @@
1
+ """Prompts for the agent coordinator."""
2
+
3
+ from __future__ import annotations
4
+
5
+ COORDINATOR_SYSTEM = """You coordinate HeyLead in-process agents.
6
+ Read the commons digest, then decide.
7
+
8
+ Decisions:
9
+ - none: sidecar digest is enough
10
+ - note: leave one short note for the next tick
11
+ - hold: a human should look (stale sibling, conflicting notes, or you are unsure)
12
+
13
+ Do not write LinkedIn messages. Do not turn other agents on or off.
14
+ Default to none when nothing is wrong."""
15
+
16
+
17
+ def build_coordinator_context(*, trigger_agent: str, campaign_id: str) -> str:
18
+ camp = campaign_id or "(account)"
19
+ return f"Trigger: {trigger_agent}\nCampaign: {camp}\nRead tools if you need the digest."
@@ -67,7 +67,10 @@ SENTIMENT = _obj({
67
67
  AGENT_STEP = _obj({
68
68
  "action": {
69
69
  "type": "string",
70
- "enum": ["read_thread", "read_timeline", "read_icp", "read_fit", "decide"],
70
+ "enum": [
71
+ "read_thread", "read_timeline", "read_icp", "read_fit",
72
+ "read_commons", "write_commons", "decide",
73
+ ],
71
74
  },
72
75
  "decision": {
73
76
  "type": "string",
@@ -75,13 +78,17 @@ AGENT_STEP = _obj({
75
78
  },
76
79
  "reason": _STR,
77
80
  "done": {"type": "boolean"},
81
+ "note": _STR,
78
82
  })
79
83
 
80
84
  # ICP research vertical — extra strings are a flat filter patch (empty = no change).
81
85
  ICP_AGENT_STEP = _obj({
82
86
  "action": {
83
87
  "type": "string",
84
- "enum": ["read_icp", "preview_search", "read_filters", "decide"],
88
+ "enum": [
89
+ "read_icp", "preview_search", "read_filters",
90
+ "read_commons", "write_commons", "decide",
91
+ ],
85
92
  },
86
93
  "decision": {
87
94
  "type": "string",
@@ -89,6 +96,7 @@ ICP_AGENT_STEP = _obj({
89
96
  },
90
97
  "reason": _STR,
91
98
  "done": {"type": "boolean"},
99
+ "note": _STR,
92
100
  "titles_include": _STR,
93
101
  "titles_exclude": _STR,
94
102
  "locations_include": _STR,
@@ -101,7 +109,10 @@ ICP_AGENT_STEP = _obj({
101
109
  REPLAN_AGENT_STEP = _obj({
102
110
  "action": {
103
111
  "type": "string",
104
- "enum": ["read_plan", "read_signals", "read_thread", "read_status", "decide"],
112
+ "enum": [
113
+ "read_plan", "read_signals", "read_thread", "read_status",
114
+ "read_commons", "write_commons", "decide",
115
+ ],
105
116
  },
106
117
  "decision": {
107
118
  "type": "string",
@@ -109,6 +120,7 @@ REPLAN_AGENT_STEP = _obj({
109
120
  },
110
121
  "reason": _STR,
111
122
  "done": {"type": "boolean"},
123
+ "note": _STR,
112
124
  "remaining_json": _STR,
113
125
  })
114
126
 
@@ -116,7 +128,10 @@ REPLAN_AGENT_STEP = _obj({
116
128
  CLOSER_AGENT_STEP = _obj({
117
129
  "action": {
118
130
  "type": "string",
119
- "enum": ["read_thread", "read_contact", "read_calendar_target", "decide"],
131
+ "enum": [
132
+ "read_thread", "read_contact", "read_calendar_target",
133
+ "read_commons", "write_commons", "decide",
134
+ ],
120
135
  },
121
136
  "decision": {
122
137
  "type": "string",
@@ -124,7 +139,23 @@ CLOSER_AGENT_STEP = _obj({
124
139
  },
125
140
  "reason": _STR,
126
141
  "done": {"type": "boolean"},
142
+ "note": _STR,
127
143
  "attendee_email": _STR,
128
144
  "start_iso": _STR,
129
145
  "duration_minutes": _STR,
130
146
  })
147
+
148
+ # Coordinator — digest is sidecar-authored; the loop may note or hold.
149
+ COORDINATOR_AGENT_STEP = _obj({
150
+ "action": {
151
+ "type": "string",
152
+ "enum": ["read_commons", "read_digest", "write_commons", "decide"],
153
+ },
154
+ "decision": {
155
+ "type": "string",
156
+ "enum": ["none", "note", "hold"],
157
+ },
158
+ "reason": _STR,
159
+ "done": {"type": "boolean"},
160
+ "note": _STR,
161
+ })
@@ -1355,6 +1355,12 @@ HOT_LEAD_CLOSER_RESULT_CHARS = 2000
1355
1355
  HOT_LEAD_CLOSER_MAX_BOOKS_PER_DAY = 5
1356
1356
  HOT_LEAD_CLOSER_VALID_DECISIONS = frozenset({"book", "hold", "none"})
1357
1357
 
1358
+ COORDINATOR_MAX_STEPS = 2
1359
+ COORDINATOR_MAX_TOKENS = 600
1360
+ COORDINATOR_TIMEOUT_SECONDS = 20
1361
+ COORDINATOR_RESULT_CHARS = 1500
1362
+ COORDINATOR_VALID_DECISIONS = frozenset({"none", "note", "hold"})
1363
+
1358
1364
  STRATEGIST_AVAILABLE_ACTIONS = frozenset({
1359
1365
  "profile_view",
1360
1366
  "follow",
@@ -35,7 +35,7 @@ _DB_RETRY_BACKOFF = 0.1 # seconds, doubles each attempt
35
35
  # dedup read it as "already in a campaign" and never let the person back in.
36
36
  # 7: outreaches.chat_id (and headline A/B columns) — a v6 stamp skipped the
37
37
  # ALTER, so planning died with `no such column: o.chat_id`.
38
- SCHEMA_VERSION = 9 # 9: contacts.timezone (per-prospect planning windows); 8: versioned outreach sync
38
+ SCHEMA_VERSION = 10 # 10: agent_commons (beats + notes); 9: contacts.timezone
39
39
 
40
40
  # Singleton connection — avoids opening multiple connections per process
41
41
  # which causes "database is locked" errors with WAL mode.
@@ -605,6 +605,24 @@ CREATE TABLE IF NOT EXISTS company_posts_tracked (
605
605
  );
606
606
  CREATE INDEX IF NOT EXISTS idx_cpt_watchlist ON company_posts_tracked(watchlist_id);
607
607
  CREATE INDEX IF NOT EXISTS idx_cpt_post_id ON company_posts_tracked(post_id);
608
+
609
+ -- In-process agent scratch (heartbeat + short notes for the next tick)
610
+ CREATE TABLE IF NOT EXISTS agent_commons (
611
+ id TEXT PRIMARY KEY,
612
+ kind TEXT NOT NULL,
613
+ agent TEXT NOT NULL,
614
+ campaign_id TEXT NOT NULL DEFAULT '',
615
+ outreach_id TEXT,
616
+ body TEXT,
617
+ decision TEXT,
618
+ reason TEXT,
619
+ created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
620
+ expires_at INTEGER
621
+ );
622
+ CREATE INDEX IF NOT EXISTS idx_agent_commons_beat
623
+ ON agent_commons(campaign_id, agent, kind);
624
+ CREATE INDEX IF NOT EXISTS idx_agent_commons_notes
625
+ ON agent_commons(campaign_id, kind, expires_at);
608
626
  """
609
627
 
610
628
 
@@ -2278,6 +2296,31 @@ def _apply_migrations(conn: sqlite3.Connection) -> None:
2278
2296
  _reraise_if_migration_interrupted(e)
2279
2297
  logger.warning("Migration: outreach dedup failed: %s", e)
2280
2298
 
2299
+ try:
2300
+ conn.execute("SELECT 1 FROM agent_commons LIMIT 0")
2301
+ except sqlite3.OperationalError as e:
2302
+ _reraise_if_migration_interrupted(e)
2303
+ conn.executescript("""
2304
+ CREATE TABLE IF NOT EXISTS agent_commons (
2305
+ id TEXT PRIMARY KEY,
2306
+ kind TEXT NOT NULL,
2307
+ agent TEXT NOT NULL,
2308
+ campaign_id TEXT NOT NULL DEFAULT '',
2309
+ outreach_id TEXT,
2310
+ body TEXT,
2311
+ decision TEXT,
2312
+ reason TEXT,
2313
+ created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
2314
+ expires_at INTEGER
2315
+ );
2316
+ CREATE INDEX IF NOT EXISTS idx_agent_commons_beat
2317
+ ON agent_commons(campaign_id, agent, kind);
2318
+ CREATE INDEX IF NOT EXISTS idx_agent_commons_notes
2319
+ ON agent_commons(campaign_id, kind, expires_at);
2320
+ """)
2321
+ conn.commit()
2322
+ logger.info("Migration: added agent_commons table")
2323
+
2281
2324
 
2282
2325
  def _backfill_global_contacts(conn: sqlite3.Connection) -> None:
2283
2326
  """One-time backfill: create global_contacts from existing campaign contacts.
@@ -28,6 +28,18 @@ from .ops_log import run_traced
28
28
  _CHANGELOG = """\
29
29
  # HeyLead Changelog
30
30
 
31
+ ## v0.10.334 (2026-09-09)
32
+ - New: after each sibling loop a coordinator upserts a digest and
33
+ beat. inspect(action='commons') shows it; act can persist a
34
+ campaign hold. edit_campaign(enable_coordinator_agent=on).
35
+ Never sends LinkedIn (#279)
36
+
37
+ ## v0.10.333 (2026-09-09)
38
+ - New: in-process agents leave an inspectable commons — a heartbeat after
39
+ every loop, and one short note per run for the next tick.
40
+ inspect(action='commons') shows beats, live notes, and who went dark
41
+ (#275)
42
+
31
43
  ## v0.10.332 (2026-09-09)
32
44
  - New: brand_strategy(action="set_headline", focus="...") sets the LinkedIn
33
45
  headline to exactly the text you pass. execute and makeover both write a
@@ -1234,9 +1246,12 @@ mcp = FastMCP(
1234
1246
  " Never paste model-authored text as the LinkedIn message; the send\n"
1235
1247
  " tools generate it. Agents default to observe. Turn act on with\n"
1236
1248
  " edit_campaign(enable_reply_agent='on'),\n"
1237
- " edit_campaign(enable_strategist_replan_agent='on'), or\n"
1238
- " edit_campaign(enable_hot_lead_closer='on'). Use 'observe' to\n"
1239
- " return to logging-only, 'off' to disable.\n"
1249
+ " edit_campaign(enable_strategist_replan_agent='on'),\n"
1250
+ " edit_campaign(enable_hot_lead_closer='on'), or\n"
1251
+ " edit_campaign(enable_coordinator_agent='on'). Use 'observe' to\n"
1252
+ " return to logging-only, 'off' to disable. If they ask what the\n"
1253
+ " agents left for the next tick, what the swarm thinks, or who\n"
1254
+ " went dark, call inspect(action='commons').\n"
1240
1255
  " - book_meeting() — put an agreed call on your Google Calendar and invite them\n"
1241
1256
  " - suggest_next_action() — AI-recommended next step\n"
1242
1257
  " - analytics(action='report') — detailed analytics with outcomes and stale lead warnings\n"
@@ -2058,6 +2073,7 @@ async def edit_campaign(
2058
2073
  enable_reply_agent: str = "",
2059
2074
  enable_strategist_replan_agent: str = "",
2060
2075
  enable_hot_lead_closer: str = "",
2076
+ enable_coordinator_agent: str = "",
2061
2077
  engagement_mode: str = "",
2062
2078
  max_followups: int = 0,
2063
2079
  followup_delay_days: str = "",
@@ -2114,6 +2130,8 @@ async def edit_campaign(
2114
2130
  "observe". Empty keeps the current value.
2115
2131
  enable_hot_lead_closer: Hot-lead closer: "on", "off", or "observe".
2116
2132
  Empty keeps the current value.
2133
+ enable_coordinator_agent: Coordinator digest/hold: "on", "off", or
2134
+ "observe". Empty keeps the current value.
2117
2135
  engagement_mode: Engagement style: "auto" (30% react / 70% comment),
2118
2136
  "comment_only", or "react_only".
2119
2137
  max_followups: Max follow-up messages (1-5). 0 to keep current.
@@ -2162,6 +2180,7 @@ async def edit_campaign(
2162
2180
  enable_reply_agent=enable_reply_agent,
2163
2181
  enable_strategist_replan_agent=enable_strategist_replan_agent,
2164
2182
  enable_hot_lead_closer=enable_hot_lead_closer,
2183
+ enable_coordinator_agent=enable_coordinator_agent,
2165
2184
  engagement_mode=engagement_mode,
2166
2185
  max_followups=max_followups,
2167
2186
  followup_delay_days=followup_delay_days,
@@ -2294,11 +2313,12 @@ async def inspect(
2294
2313
  Args:
2295
2314
  action: What to show:
2296
2315
  "agents" — one-screen digest of holds, replans, closer, skips, jobs (default)
2297
- "holds" — fresh hold_for_operator rows (reply agent + closer)
2316
+ "holds" — fresh hold_for_operator rows and coordinator campaign holds
2298
2317
  "replans" — today's strategist_replan_decision rows
2299
2318
  "closer" — today's hot_lead_closer_decision rows
2300
2319
  "skips" — recent reply skips (hard gates, cap, dedup, agent skip)
2301
2320
  "jobs" — pending scheduler jobs and recent gated-job refusals
2321
+ "commons" — digest, beats, live notes, coordinator hold, stale liveness
2302
2322
  campaign_id: Optional campaign filter (full id or prefix).
2303
2323
  outreach_id: Optional outreach filter (full id or prefix).
2304
2324
  limit: Max rows per slice, 1-100 (default 20).