Project config
The project config module is the discovery surface for CLI, inspection UI, and loadAdlProject(). Implementations can live at arbitrary paths; only adl.config.* at the project root is required.
Design decisions
Section titled “Design decisions”- Static registry at load time — no dynamic registration or runtime plugin scan.
- Arrays of definitions; each carries its own
id(agents/workflows) orname(templates from filename). - Runtime via config — tooling reads
config.adlfrom the loaded config; it does not import a project runtime file by convention path. - JSON config (
adl.config.json) suitsnameonly — registries andadlneed TS/JS for imports.
AdlProjectConfig
Section titled “AdlProjectConfig”import type { AdlProjectConfig } from "@agent-dev-lab/core";import { adl } from "#adl";
import { researcher, writer } from "./agents";import { literatureReview, quickSummary } from "./workflows";import { findPapersPrompt, outlinePrompt } from "./prompts";
export { adl }; // optional — tooling uses the default export's `adl` field
export default { name: "my-research",
/** Required for CLI / inspection UI execution — not a fixed file path */ adl,
agents: [researcher, writer], workflows: [literatureReview, quickSummary], templates: [findPapersPrompt, outlinePrompt],
tools: { /* shared AI SDK ToolSet */ }, defaults: { /* optional project-wide defaults — TBD */ },} satisfies AdlProjectConfig;Validation at load time:
namerequired- Unique
idper agent/workflow (throws on duplicate) - Unique
nameper template (throws on duplicate)
loadAdlProject
Section titled “loadAdlProject”import { loadAdlProject, type LoadedAdlProject } from "@agent-dev-lab/core";
const project: LoadedAdlProject = await loadAdlProject();
project.getAdl();project.getWorkflow("literature-review");project.listAgentIds();Discovery walks upward from cwd for adl.config.* (findAdlProjectRootFromCwd) or accepts an explicit root via ADL_PROJECT_ROOT. The inspection UI uses the same loadAdlProject() path as the CLI — never a hard-coded src/adl.ts import.
Execution
Section titled “Execution”One primitive: workflow.run(input) — no separate runWorkflow() helper.
| Entry | What it does |
|---|---|
workflow.run(input) | The execution primitive |
adl run <id> | Planned: load project → getWorkflow(id).run(...) |
adl dev / UI | Planned: list ids + trigger by id |
| Direct import | Skip registry; still use .run |
import { loadAdlProject } from "@agent-dev-lab/core";
import { literatureReview } from "./workflows/literature-review";
// By referenceconst handle = literatureReview.run({ topic: "CRISPR delivery" });const output = await handle.result;
// By id after loadAdlProjectconst project = await loadAdlProject();const workflow = project.getWorkflow("literature-review");const handleById = workflow!.run({ topic: "CRISPR delivery" });WorkflowRunHandle
Section titled “WorkflowRunHandle”workflowRunId— available immediately for store subscription / future SSEresult—Promise<Output>cancel()— cooperative cancellation (partial propagation today)
Authors receive WorkflowContext inside adl.createWorkflow({ run: async (input, ctx) => … }).
CLI (planned)
Section titled “CLI (planned)”adl run literature-review --input '{"topic":"…"}'adl workflows listadl agents listImplemented today: adl dev only.
Why registries stay static
Section titled “Why registries stay static”| Scenario | Approach |
|---|---|
| Different models per environment | defaults or env in adl.config.ts |
| A/B two workflows | List both; choose at CLI or getWorkflow(id).run(...) |
| Monorepo multiple projects | Multiple roots; loadAdlProject({ root }) each |
See Project setup and Runtime.