Skip to main content

Extending KanbanAI

This guide is for contributors who want to add new capabilities (agents, listeners, routes) without breaking the existing layering between core/ and server/.

Architecture recap

  • core/:
    • Business logic, abstract repository interfaces, and data access contracts.
    • Defines repository interfaces in core/src/repos/interfaces.ts and type definitions in core/src/db/types.ts.
    • No framework or runtime-specific code; database-agnostic.
  • server/:
    • Hono app, Bun entrypoints, HTTP/WebSocket routes, adapters for core services.
    • Owns Drizzle schema definitions in server/src/db/schema/ and implements concrete repositories in server/src/repos/.
    • Event bus wiring and module-level READMEs (server/src/*/README.md) describing each domain.
  • client/:
    • React + Vite UI that talks to the API + WebSockets and uses shared types from shared/.
Most extensions involve:
  • Adding/expanding a core service or listener.
  • Adding routes/handlers in server that adapt HTTP/WebSockets to core.

Adding a new agent

  1. Define the agent behavior in core/src/agents:
    • Create a new folder (e.g. core/src/agents/my-agent) implementing the Agent interface from core/src/agents/types.ts.
    • Implement run and resume, streaming messages via the provided emitter.
  2. Add availability detection (optional but recommended):
    • Implement an availability(): Promise<boolean> method to check if required executables or dependencies are installed.
    • Use locateExecutable() from core/src/agents/sdk/executable.ts for CLI-based agents.
    • Agents without availability checks are registered unconditionally.
  3. Register in server via server/src/agents/registry.ts:
    • Add your agent to the ALL_AGENTS array.
    • The server uses initializeServerAgents() at startup to dynamically register only available agents.
    • Availability checks ensure agents are only registered when their dependencies are installed.
  4. Expose to the UI:
    • Once registered, the agent appears in the /agents endpoint response.
    • Add any agent-specific profile schema/validation as needed.
  5. Wire profiles (optional):
    • If your agent needs custom profile schema, integrate with core/agents/profiles and validate configs before use.
The dynamic registration system automatically skips agents whose availability() method returns false, preventing runtime errors when dependencies are missing.

Adding a new event listener

  1. Define event types in core/src/events/types.ts if you are introducing a new event kind.
  2. Publish events from the relevant service:
    • Use the AppEventBus to publish domain events from core services.
  3. Register listeners:
    • Add a new listener module (or extend an existing one) under core/src/*/listeners.ts.
    • Wire it into registerEventListeners in server/src/events/register.ts.
  4. Broadcast over WebSockets (optional):
    • If the event should reach clients in realtime, subscribe to it in server/src/ws/listeners.ts and map it to a WebSocket message defined in shared/src/types/kanban.ts.

Adding a new HTTP route

  1. Add core functionality (if needed):
    • Implement the underlying behavior in core/ (service or helper).
  2. Create a router/handlers in server/src:
    • Follow existing patterns in modules like projects, attempts, or github.
    • Keep Hono handlers thin: parse/validate input, call core, map results to JSON.
  3. Wire the router into app.ts:
    • Route under /api/v1 with a clear prefix (e.g. /my-feature).

Where to read more

  • server/src/*/README.md – domain-specific docs for:
    • attempts, github, tasks, projects, git, fs, ws, editor, settings, agents.
  • docs/core/ai-attempts.md – how Attempts work end-to-end.
  • docs/core/git-integration.md – git helpers and events.
  • docs/core/agents-and-profiles.md – agents module and profiles.