Model the system / 02

Definitions and instances

A definition describes a kind of agent. An instance is one durable agent assembled from that definition plus persisted data. Keeping them separate is what makes dynamic provisioning possible without turning configuration into code generation.

Definitions live in code

agents/release-planner/agent.ts is discovered as therelease-planner route. You do not repeat that identity insidedefineAgent. The generated route map gives clients a closed, type-safe set of definitions.

agents/release-planner/agent.tstypescript
import { defineAgent } from "glove-foundry";

export default defineAgent({
  description: "Turns an objective into a verified release plan",
  systemPrompt: (_agent, ctx) => promptFor(ctx.message, ctx.history),
  tools: (_agent, ctx) => toolsFor(ctx.agentInstance, ctx.message),
});

Colocated primitives follow the same rule. A tool, app, memory adapter, subscriber, or schedule receives its runtime identity from its file during discovery. In static code, import the value itself: install(releaseNotes), not install("release-notes").

Instances live in data

An instance records what a particular agent has been given: its runtime ID, definition route, workspace, application installations, playbooks, schedules, and arbitrary context. Foundry can load that record after a restart and reconstruct the agent from the current code definition.

agents/release-planner/instances.tstypescript
import { defineAgentInstance, install } from "glove-foundry";
import releasePlanner from "./agent.js";
import releaseNotes from "./apps/release-notes.app.js";

export const coordinator = defineAgentInstance(releasePlanner, {
  // Instance identity is data. It may instead be assigned by your adapter.
  id: "release-coordinator-01",
  workspaceId: "launch-q4",
  context: { role: "release-coordinator" },
  installations: [install(releaseNotes, { channel: "launch" })],
  playbooks: [],
});

Where strings are correct

SituationReferenceWhy
Definition imports another static primitiveImported objectRenames fail at compile time and editors follow the reference.
Generated client selects an agent routeGenerated string unionThe HTTP route is serialized, but still checked against discovered files.
Persisted instance points to a definitionSerialized routeData must survive processes and deployments.
Run points to an instance or conversationRuntime IDThese identities are created and updated dynamically.

Instances can change

Install or uninstall applications, replace playbooks, update instance context, add schedules, or move workspace bindings through the data adapter. The next run reconstructs from the latest persisted record and resolves every lazy definition again against the new message.

Instances can be provisioned by events

A playbook subscription can target an existing singleton, one agent per external thread, one per event, or a fixed fan-out. When an inbound transmission matches and no target instance exists, the provisioning adapter atomically creates the instance and conversation before dispatch. Duplicate delivery is claimed idempotently.