Skip to main content
A manifest is the deterministic fingerprint of your agent at a point in time — its tools, prompts, models, sub-agents, and output schema. DecimalAI auto-detects manifests for OpenAI Agents and LangChain. Use register_manifest() only when you need full control or use a custom framework. See the Manifests guide for the conceptual model.

decimalai.register_manifest()

Explicitly register an agent’s configuration for version tracking.
str
required
Name of the agent.
list[dict]
Tool descriptors: [{"name": "...", "schema": {...}}].
dict
Prompt templates: {"system": "..."}.
dict
Model configs: {"default": {"provider": "openai", "model": "gpt-4o"}}.
list[dict]
Sub-agent references: [{"name": "flight_agent"}].
dict
Output contract JSON schema.
str
Human-readable version label (e.g., "v2.1").
For OpenAI Agents and LangChain, manifests are auto-detected from your agent configuration. Use register_manifest() only when you need full control or use a custom framework.
Returns the backend registration response (a dict):
str
Always "ok" on a successful registration.
str
ID of the manifest row this config resolved to.
str
Deterministic content hash of the manifest — identical configs hash identically.
str
The human-readable version label, echoed back.
bool
true only when a fresh manifest row was created. A re-register of an unchanged config dedups and returns false.
int
Number of manifest components captured across all surfaces.
str | null
ID of the generated compatibility report, or null if none was produced.

decimalai.flush_manifest_for_ci()

Register the manifest as a regression-check candidate and write its ID for the next CI step to read. This is the helper your CI init script (typically init_for_decimal.py) calls under DECIMALAI_MODE=manifest_only, after building the agent. It requires a positional agent_name.
Components are taken from what you pass, not from global SDK state: supply chain= (below) or the explicit tools / prompts / models dicts, otherwise you register an empty manifest and every later PR diffs against nothing. The manifest ID is written to (in order): the output_path= you pass, else $GITHUB_OUTPUT if set (appended as decimal_manifest_id=<id>, the standard GitHub Actions mechanism), else ./decimal_manifest_id.txt in the current directory. An explicit output_path therefore overrides the GitHub Actions handoff — the Action itself only auto-discovers $GITHUB_OUTPUT and ./decimal_manifest_id.txt, so if you write somewhere else, pass that ID to the Action’s candidate-manifest-id input yourself. The path actually used comes back as output_path in the return value.
Inside GitHub Actions $GITHUB_OUTPUT is always set, so branch 2 always wins and ./decimal_manifest_id.txt is never written. And $GITHUB_OUTPUT is per-step — the file the next step sees is a fresh one, so the Action’s auto-discovery finds neither source and stops with “No candidate-manifest-id provided or discoverable”. Give the step an id: and pass candidate-manifest-id: ${{ steps.<id>.outputs.decimal_manifest_id }} to the Action explicitly.
You can also let flush_manifest_for_ci introspect a LangChain/LangGraph agent instead of passing component dicts:
See the Regression Check guide for the full CI setup.

What’s next

Evaluations

Push scores onto traces and read back the verdict.

Manifests guide

Conceptual deep-dive on what a manifest is and how diffs work.