Agent as an injectable driver

Updated · View the entry on sijie.xyz ↗

✓ LANDED

The agent core is now an independently launchable module via Bridge/Driver pattern.

The design

Agent core = independently launchable module via Bridge/Driver.

The abstraction lives in backend/agentcore/ (deliberately OUTSIDE internal/):

  • driver.go: defines the Driver interface with methods: Persona, Skill, RunSkill, ExtMCPURL, Plugins, SearchCorpus, ListCorpus, GetCorpus, Resolve
    • Agent core is the Abstraction; Driver is the Implementor
  • bridge.go: adapts any Driver onto the loop's internal ports (driverSandbox → sandbox.Runner, driverSkillGetter, driverMCPGetter, driverResolver → credential resolver)
  • agentcore.go: public facade over the eino loop types
  • Launch handle: BuildVisitorAgent(ctx, d Driver, in *LaunchInput) (visitor_build.go:50)

The proof it's real

eval-harness/ is a SEPARATE Go module whose EvalDriver (eval_driver.go) implements the interface and runs the REAL eino loop on canned data:

  • golden_assembly_test.go (golden-path scenarios)
  • plugin_assembly_test.go / booker_assembly_test.go (plugin-specific tests)
  • retrieval_assembly_test.go (retrieval / corpus tests)
  • launch_test.go (end-to-end) + the *_live_test.go set on a real model

Only eval launches through the handle today — "eval is just another consumer" holds in the type system, not yet in prod: as of 2026-09-07 (36789537d) BuildVisitorAgent has exactly one non-test caller (eval-harness/main.go:164, candidate.go:138), and no package under backend/internal or backend/cmd imports agentcore. The prod web path is internal/routes/public/sessions.go → capreg.AssembleVisitorBundle → inference.RunAgentTurn. The intended end state — prod passes a prod Driver, eval passes an EvalDriver — is the "Remaining" item below.

Iron rules

  1. Re-export of internal/ types = a dependency, forbidden. Callers import only agentcore.
  2. Fixtures live ONLY in the caller (eval-harness). Backend stays fixture-free.
  3. Guarded by check-no-mock: ensures no mock/fixture code creeps into backend.

Class view — the textbook Bridge

classDiagram
  class Driver {
    <<interface - the Implementor>>
    +Persona(ctx) (Persona, error)
    +Skill(ctx) (*VisitorSkillSpec, error)
    +RunSkill(ctx, SkillRun) (SkillResult, error)
    +ExtMCPURL(ctx) (string, error)
    +Plugins(ctx) ([]PluginSpec, error)
    +SearchCorpus(ctx, query) ([]CorpusHit, error)
    +ListCorpus(ctx, parentPath, page) ([]CorpusHit, error)
    +GetCorpus(ctx, path) (CorpusDoc, error)
    +Resolve(ctx) (Cred, error)
  }
  class LaunchInput {
    OwnerID string
    Mode string
    ConversationID string
    CodeID string
    SystemPromptOverride string
    GrantedCapabilities []string
  }
  class VisitorAgent {
    Labels map[string]string
    ReturnDirectly map[string]bool
    SystemPrompt string
    Tools []tool.BaseTool
  }
  class bridgeAdapters {
    bridge.go - driverSandbox / driverSkillGetter / driverMCPGetter / driverResolver
    wrap a Driver into the loop's internal ports
  }
  class EvalDriver {
    eval-harness, separate go.mod
    canned data behind the interface
  }
  class BuildVisitorAgent {
    <<launch handle>>
    takes ctx, Driver, *LaunchInput
    returns (*VisitorAgent, error)
  }
  bridgeAdapters ..> Driver : wraps
  Driver <|.. EvalDriver
  BuildVisitorAgent ..> Driver : consumes any
  BuildVisitorAgent ..> LaunchInput : input
  BuildVisitorAgent --> VisitorAgent : builds

Prod and eval are meant to differ by one constructor argument — that is the whole pattern (today only the eval side of it is wired; see above).

Earlier deviation (remediated)

The earlier deviation (fixture files welded into backend/agentcore/) has been REMEDIATED — the directory is fixture-free; canned data lives only behind the injected Driver ("the Driver IS the environment").

Remaining (roadmap layer③)

Promote inject-and-launch from test-only to first-class runtime: parallel prompt experiments — the missing "quality half" of eight-controls-applied.


See also: entry-agnostic-agent (inward/outward symmetry); eval-harness-on-prod-loop (historical context).

Related notes