Skip to main content

dagstack.toml schema

The full table of plugin manifest fields. The normative JSON Schema 2020-12 lives in the spec repository: _meta/manifest.schema.json.

The manifest may live in one of four formats:

  • dagstack.toml (Python and Go convention) — the primary format.
  • dagstack.json (TypeScript / Node convention).
  • A [tool.dagstack.plugin] section in pyproject.toml (for Python plugins on PyPI).
  • A dagstack field in package.json (for TypeScript plugins on npmjs.org).

When several formats are present, precedence is dagstack.tomldagstack.json → embedded in the package.

Root section [plugin]

Required fields

FieldTypeDescription
schema_versionstringManifest JSON-schema version. On v1.0, "1".
namestringPlugin name, unique within its kind. Lower-case letters, digits, -, _.
kindstringPlugin kind — opaque to the core; the application defines the list of kinds.
runtimestring | string[]Execution runtime: "in_process" / "mcp_stdio" / "mcp_http". An array is allowed.
core_versionstringSemver range for the dagstack-plugin-system version. Example: "^0.2", ">=0.3.0 <1.0.0".
entry_pointstringModule and class: "module:ClassName". REQUIRED for in_process.

Metadata

FieldTypeDefaultDescription
versionstringSemver version of the plugin itself.
descriptionstringShort human-readable description.
authorsstring[][]List of authors.
homepagestringURL of the plugin's home page.
licensestringSPDX licence identifier (for example, "Apache-2.0").

Lifecycle and ordering (ADR-0002)

FieldTypeDefaultDescription
priorityint (0..100)0Priority for dispatch and lifecycle ordering. Higher = earlier / more important. The range [1000, ∞) is reserved for horizontal middleware (ADR-0005).
depends_onstring[] | object[][]List of dependency plugin names (or an array of {kind, name} objects for the full form).
tryfirstboolfalseDebug escape hatch: forces this plugin to run first. Not a substitute for priority / depends_on in production.
trylastboolfalseForces this plugin to run last. Incompatible with tryfirst=true.
startup_timeout_secint30Timeout for the plugin's setup().
teardown_timeout_secint15Timeout for teardown().

Dispatch (ADR-0002)

FieldTypeDefaultDescription
execution_modelstring"sync""async" / "sync" / "thread_cpu_bound" / "process_cpu_bound".
in_process_onlyboolfalseIf true, the plugin lives only in the in_process runtime (it cannot be isolated through MCP).
supports_languagesstring[][]For capability dispatch: languages the plugin handles.
supports_extensionsstring[][]For capability dispatch: file extensions.
supports_mime_typesstring[][]For capability dispatch: MIME types.
fallbackboolfalseIf true, the plugin accepts any input that did not match another plugin. Exactly one per kind.
capabilitiesstring[][]Arbitrary capability identifiers (for governance filtering and custom routing).

[plugin.resources] section

Declares the resources the plugin expects to receive through PluginContext.resources.

FieldTypeDefaultDescription
requiredstring[][]Required resources. If they are missing, the plugin is marked unavailable.
optionalstring[][]Optional resources. Accessing them yields None when not provided.

Standard resource names are listed on the Standard resources page.

[plugin.unit_of_work] section

For long-running plugins that execute UoWs through an orchestrator (ADR-0003 §5).

FieldTypeDefaultDescription
declaredboolfalsetrue — the plugin is a UoW plugin.
partition_keystringSharding key (tenant_id, repo_id, ...).
estimated_duration_secintDuration estimate — a hint for the scheduler.
idempotency_modestring"none""input_hash" / "output_hash" / "none".
checkpointableboolfalseWhether the plugin supports resume via ctx.checkpoint.
content_hashstring[][]Fields used to compute the idempotency key.

[plugin.mcp_stdio] section (for runtime = "mcp_stdio")

FieldTypeDefaultDescription
commandstring[]REQUIRED. Subprocess launch command (arguments are passed as an array).
working_dirstringprocess cwdSubprocess working directory.
envobject{}Environment variables for the subprocess.
startup_timeout_secint30Initial handshake timeout.

[plugin.mcp_http] section (for runtime = "mcp_http")

FieldTypeDefaultDescription
urlstringREQUIRED. Base URL of the MCP service.
auth_headerstringHTTP header name for the bearer token.
auth_secret_envstringName of the env variable holding the secret (the host substitutes it into the header).
timeout_secint60Per-request timeout.
tls_ca_bundlestringPath to a corporate CA bundle for TLS (optional).

[plugin.metadata] section

Arbitrary keys, not interpreted by the plugin-system core. They may be used by the application or by horizontal middleware.

[plugin.metadata]
owner_team = "search-platform"
runbook = "https://runbook.example.org/chunker"
on_call = "search-oncall@example.com"

Full example

plugins/advanced-chunker/dagstack.toml
[plugin]
schema_version = "1"
name = "advanced-chunker"
kind = "chunker"
runtime = ["in_process", "mcp_stdio"]
core_version = ">=0.1.0,<1.0.0"
entry_point = "plugin:AdvancedChunker"
version = "1.2.0"
description = "Tree-sitter-based semantic chunker with a length fallback."
authors = ["dagstack"]
license = "Apache-2.0"

priority = 50
depends_on = ["tokenizer"]
execution_model = "thread_cpu_bound"

supports_languages = ["python", "typescript", "go"]
supports_extensions = [".py", ".ts", ".go"]
fallback = false

[plugin.resources]
required = ["clock"]
optional = ["blob_store"]

[plugin.unit_of_work]
declared = true
partition_key = "repo_id"
idempotency_mode = "input_hash"
checkpointable = true

[plugin.mcp_stdio]
command = ["python", "-m", "advanced_chunker.server"]
startup_timeout_sec = 60

[plugin.metadata]
owner_team = "search-platform"
runbook = "https://runbook.example.org/chunker"

Validation

The core validates the manifest at discover() time against JSON Schema 2020-12. Violations raise ManifestInvalid with the offending field and the type of error. Typical failures:

  • A required field is missing (name, kind, runtime, ...).
  • Wrong type (priority = "50" instead of a number).
  • Invalid enum value (runtime = "in-process" with a hyphen instead of "in_process").
  • Semver mismatch (core_version = "0.1" instead of a range).

See also