feat(agents): require explicit agent config to enable agent per project#897
feat(agents): require explicit agent config to enable agent per project#897
Conversation
The new `isAgentEnabledForProject()` guard requires an explicit `agent_configs` row before any trigger can fire. Integration tests that called `handle()` and expected a non-null result were failing because no agent config was seeded. - Seed `agent_configs` + `agent_trigger_configs` rows in tests that expect triggers to fire (trigger-registry, pm-provider-switching, github-personas) - Export `clearAgentEnabledCache()` from agentConfigsRepository for test isolation (the 5s TTL cache was causing false negatives when tests ran within the TTL window of a prior test that had no config) - Call `clearAgentEnabledCache()` in `truncateAll()` so every `beforeEach` starts with a clean cache alongside a clean DB Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CI Failures ResolvedRoot CauseThe new Additionally, the 5-second TTL in-memory cache for Fixes Applied
Verification
🕵️ claude-code · claude-sonnet-4-6 · run details |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
nhopeatall
left a comment
There was a problem hiding this comment.
Summary
LGTM — Clean, well-structured enforcement of agent opt-in gating. The guard is applied consistently at all entry points (trigger resolution, manual runs, tRPC endpoint), and the defense-in-depth approach of also flipping defaultEnabled to false in all YAML definitions is sound. Tests cover all new paths.
Observations (all verified, no issues)
-
Guard coverage is complete: All trigger handlers flow through
checkTriggerEnabled→isTriggerEnabled→isAgentEnabledForProject. Manual runs check directly. The tRPCruns.triggerendpoint checks before dispatching. Theretryendpoint is covered viatriggerRetryRun→triggerManualRunwhich has the guard. The queue worker paths (manual-run,retry-run) ultimately call the same guarded functions. -
Cache pattern is consistent:
isAgentEnabledForProjectuses the same 5s TTL Map-based cache as the existinggetAgentConfigPromptsandgetMaxConcurrencyin the same file.clearAgentEnabledCache()is called intruncateAll()for test isolation. -
UI correctly separates enabled/available:
getProjectTriggersViewsplits agents intoenabledAgents(with config row) andavailableAgents(without). The backward-compatagentsalias pointing toenabledAgentsis fine. The "Enable Agent" button creates a bareagent_configsrow via the existingcreatemutation, which has a unique constraint on(projectId, agentType)preventing duplicates. -
Debug agent exemption: Correctly hardcoded in
isAgentEnabledForProjectand in thegetProjectTriggersViewfilter logic (always shown as enabled). -
Schema default change:
defaultEnabled: z.boolean().default(false)in the Zod schema ensures any new triggers added to YAML definitions without an explicitdefaultEnabledfield will default tofalse— good defense-in-depth.
🕵️ claude-code · claude-opus-4-6 · run details
Summary
agent_configsfor that projectisAgentEnabledForProject()guard — Added with 5s TTL cache toagentConfigsRepository.ts; exempts thedebugagent (always enabled)isTriggerEnabled,resolveTriggerConfigs,getTriggerParameters,getResolvedTriggerConfig), manual runs (triggerManualRun,triggerRetryRun), and tRPCruns.triggermutationdefaultEnabledchanged tofalse— All triggers in all agent YAML definitions now default tofalse(defense-in-depth). Zod schema default updated to matchgetProjectTriggersViewnow returnsenabledAgents(have config) +availableAgents(no config). UI shows only enabled agents with an "Available Agents" section featuring "Enable Agent" buttons. Empty state: "No agents enabled. Enable agents below to start processing."agents list— Shows only configured (enabled) agents; displays friendly message when none are enabledisAgentEnabledForProject; new tests for disabled-agent rejection in trigger resolution, manual runs, and tRPC endpointNo backwards compatibility — per card requirements. All existing projects will need admins to explicitly enable agents via Project Settings > Agent Configs.
No DB migration — enforcement is purely in application code.
Trello card: https://trello.com/c/0XSJdemg/416-no-agents-should-be-configured-for-a-project-by-default
Test plan
isTriggerEnabledreturnsfalsewithout agent configtriggerManualRunthrows descriptive error when agent not enabledruns.triggerreturnsBAD_REQUESTwhen agent not enabled🤖 Generated with Claude Code
🕵️ claude-code · claude-sonnet-4-6 · run details