Skip to content

feat(training-agent): add /si tenant for Sponsored Intelligence lifecycle (#3940)#3952

Draft
bokelley wants to merge 3 commits into
mainfrom
claude/issue-3940-si-training-tenant
Draft

feat(training-agent): add /si tenant for Sponsored Intelligence lifecycle (#3940)#3952
bokelley wants to merge 3 commits into
mainfrom
claude/issue-3940-si-training-tenant

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

@bokelley bokelley commented May 3, 2026

Summary

Fixes #3940. Adds the /si training-agent tenant so learners can practice the full Sponsored Intelligence session lifecycle against a deterministic training brand (Nova Brands).

  • New tenant (tenants/si.ts + v6-si-platform.ts): registers all four SI tools via the customTools merge seam (same pattern as update_rights/creative_approval in the brand tenant — SDK DecisioningPlatform has no SI interface field yet)
  • Tool catalog (tenants/tool-catalog.ts): adds si_get_offering, si_initiate_session, si_send_message, si_terminate_session under ['si']
  • Registry (tenants/registry.ts): registers the SI tenant alongside the existing six; updates module comment from "Six" to "Seven"
  • Migration 465 (db/migrations/465_si_tenant_module_pins.sql): pins tenant_ids for A3, C3, and S5 (left NULL in migration 464 pending this tenant); fixes phantom tool connect_to_si_agentsi_initiate_session in C3's c3_ex2; appends missing si_get_offering/si_terminate_session sandbox actions to S5's s5_ex1; stamps stable criterion IDs s5_ex1_sc_session_lifecycle and s5_ex1_sc_offering_integration via _append_criterion
  • Drift test (tests/integration/training-agent-tool-catalog-drift.test.ts): adds 'si' to TENANT_IDS
  • Smoke test (tenants/tenant-smoke.test.ts): adds 'si' to expected agent IDs

Implementation notes

  • Session state is in-memory per process — acceptable for the sandbox; sessions are training-scoped and not persisted across restarts
  • si_get_offering response matches the JSON schema shape: { available, offering_token, offering: { offering_id, title, summary }, matching_products: [...] }
  • si_terminate_session marks sessions as terminated: true in-map (does not delete) so a subsequent si_send_message returns SESSION_TERMINATED rather than the misleading SESSION_NOT_FOUND
  • si_terminate_session response includes the required terminated: true field per si-terminate-session-response.json schema
  • Session IDs use crypto.randomUUID() for sufficient entropy

Human task required

.github/workflows/training-agent-storyboards.yml storyboard floor assertions are not updated by this PR — agent policy prohibits editing .github/**. A human should add SI storyboard floors once the tenant is exercised in CI.

Test plan

  • pnpm test --filter server -- training-agent-tool-catalog-drift — drift detection passes for all 7 tenants
  • pnpm test --filter server -- tenant-smoke — smoke test passes with si in the agent list
  • Manually call tools/list on /si/mcp and verify four SI tools appear
  • Manually exercise the full lifecycle: si_get_offeringsi_initiate_session (passing offering_token) → si_send_messagesi_terminate_session; verify terminated: true in response
  • Verify si_send_message after terminate returns SESSION_TERMINATED error code
  • Run migration 465 against a dev DB and confirm A3/C3/S5 tenant_ids are populated
  • Confirm C3 c3_ex2 no longer references connect_to_si_agent
  • Confirm S5 s5_ex1 sandbox_actions includes all four SI tools

https://claude.ai/code/session_01SAU73ibxYgk3pdvmMJNjcF


Generated by Claude Code

claude added 3 commits May 3, 2026 06:03
…ycle (#3940)

Adds a new `si` training-agent tenant at `/si/mcp` serving the full
SI session lifecycle (si_get_offering, si_initiate_session,
si_send_message, si_terminate_session). Fixes the S5 capstone and
C3 exercises that returned `Unknown tool: si_initiate_session` due
to no tenant serving si_* tools.

Stub handlers simulate the BRAND-AGENT side of the protocol so a
learner can practice as the HOST. Nova Brands training fixture.
In-memory session state (same pattern as other training-agent state).

Also bundles education-expert findings from issue review:
- Migration 465: backfills tenant_ids for A3, C3, S5; fixes C3
  c3_ex2 phantom tool (connect_to_si_agent → si_initiate_session);
  appends stable criterion IDs to S5 s3_ex1 for recertification.
- Updates tool-catalog drift test to include si tenant.

Storyboard floors in .github/workflows/training-agent-storyboards.yml
left for human follow-up (agent infra, off-limits per policy).

https://claude.ai/code/session_01SAU73ibxYgk3pdvmMJNjcF
…ation 465

- Add si_get_offering and si_terminate_session to S5 s5_ex1 sandbox_actions
  before the _append_criterion calls — ASTM E3416-24 requires all criterion
  referenced behaviors to be prompted actions in the assessment.
- Clarify S5 tenant_ids comment: explains why brand was excluded.
- Improve C3 c3_ex2 guidance text to connect response inspection to the
  pedagogical point (SI personalization vs impression-based formats).

https://claude.ai/code/session_01SAU73ibxYgk3pdvmMJNjcF
- tenant-smoke.test.ts: add 'si' to expected agent IDs list
- si_terminate_session: add required `terminated: true` field per schema
- si_get_offering: restructure response to schema shape (offering object,
  matching_products array with name/product_id, offering_token at top level)
- si_send_message: return SESSION_TERMINATED (not SESSION_NOT_FOUND) after
  terminate by marking sessions terminated rather than deleting from map
- registry.ts: update module comment from "Six" to "Seven" tenants
- makeSessionId: use crypto.randomUUID() instead of Date.now()+Math.random()

https://claude.ai/code/session_01SAU73ibxYgk3pdvmMJNjcF
@bokelley bokelley added the claude-triaged Issue has been triaged by the Claude Code triage routine. Remove to re-triage. label May 3, 2026
@bokelley
Copy link
Copy Markdown
Contributor Author

Holding for rebase. The /si tenant is still wanted and not duplicated by any merged PR, but main has had ~30+ commits to server/src/training-agent/ since this branch was cut (#4060#4073, #4098, #4099, #4326, #4346 among others), so the rebase needs to thread through several recent changes:

Hard conflict:

  • Migration number collision465_si_tenant_module_pins.sql clashes with 465_founding_member_audit_columns.sql on main. Renumber to the next available slot (probably 476+ given current main) and re-verify migration 464_certification_module_tenants.sql still leaves the relevant tenant_ids NULL as this PR's setup assumes.

Soft conflicts (likely):

Failing CI: Server integration tests log was truncated to setup phase — could be flake against the stale base or a real registry-init regression. Re-run post-rebase to see what actually fails.

Recommended path: re-trigger via /triage execute on #3940 (the source issue), or check out the branch locally, do the migration renumber + registry merge + v6 shim brand-domain threading by hand. Estimated 1–2 hours of focused work. Not closing — this is a real feature gap, just blocked on a substantial rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude-triaged Issue has been triaged by the Claude Code triage routine. Remove to re-triage.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sponsored Intelligence: training-agent has no tenant serving si_* tools

2 participants