Skip to content

move to plugin based agents #88

Description

@zgeoff

Current model (closed):
type AgentRole = 'planner' | 'implementor' | 'reviewer';
type AgentRun = PlannerRun | ImplementorRun | ReviewerRun;
// Discriminated unions everywhere — adding a role is a cross-cutting change

Plugin model (open):
interface AgentDefinition {
role: string; // 'planner', 'implementor', 'reviewer', 'researcher', ...
trigger: HandlerPredicate; // when should this agent run?
contextAssembly: ContextAssembler; // what context does it need?
resultSchema: ZodSchema; // what does it produce?
resultHandler: ResultCommandFactory; // how to translate output → commands
concurrencyKey: ConcurrencyKeyFn; // what resource does it lock?
uiConfig: AgentUIConfig; // how to display in TUI
}

interface AgentUIConfig {
displayName: string; // 'Researcher'
activeVerb: string; // 'Researching'
badge: string; // 'RESEARCH'
section: 'active' | 'pending' | 'action'; // where in the TUI layout
detailRenderer: 'stream' | 'body' | 'diff'; // what to show in detail pane
}

The TUI mapping problem solves itself if each agent definition carries its own UI config. The TUI doesn't need to know about specific agent types — it renders based on AgentUIConfig. Your
display status derivation becomes generic:

// Instead of hardcoded: if (hasActiveImplementorRun) → 'implementing'
// Generic: if (hasActiveRunOfRole(role)) → role.uiConfig.activeVerb

What this buys you:

  • Add a researcher agent by defining a new AgentDefinition — no changes to engine, state store, or TUI
  • Handlers become generic: "when trigger matches, dispatch agent with context"
  • Result handling stays type-safe via the Zod schema

What you'd lose:

  • Exhaustive pattern matching on agent types (ts-pattern .exhaustive()) — you'd need runtime validation instead
  • Some compile-time guarantees on handler completeness

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions