Workflow Gates Runtime
Use Workflow Gates to enforce ordered process with evidence, approvals, and behavioral conformance.
Right page if: you want the practical runtime model for Workflow Gates, how they map to agent rules, and how they interact with rulesets. Wrong page if: you only need the raw workflow schema -- see https://docs.edictum.ai/docs/reference/workflows. Gotcha: rulesets and workflows are separate documents. Rulesets enforce single tool-call boundaries; Workflow Gates enforce ordered process with evidence and approvals. SDK setup paths exist for Python, TypeScript, and Go, but this page does not claim full helper-level parity across SDKs.
Workflow Gates turn the process requirements in an agent policy into runtime checks.
- A ruleset says whether one tool call is inside the policy boundary.
- A workflow says what order the agent must follow, what evidence it must produce, and when a human must approve a transition.
Use workflows when you need read -> implement -> verify -> review -> ship, with real evidence behind each boundary.
For runtime governance, Workflow Gates enforce:
- read-before-write: the agent cannot write until required source material was read.
- evidence-before-stage-advance: the agent cannot move forward until file, command, or MCP result evidence exists.
- approval-before-critical-transition: the agent pauses before high-impact transitions until approval is recorded.
- audit trail of behavioral conformance: every stage, block, approval, and evidence update is captured in the decision log.
What Workflow Gates Do
- Block tools that are not allowed in the active stage
- Require earlier stages to complete before later stages can start
- Require proof that files were read
- Require proof that specific commands were run
- Match MCP result evidence before a later stage can start
- Pause at a stage boundary for human approval
- Stop cleanly at a terminal stage
- Emit workflow snapshots into the decision log for behavioral conformance review
Policy Mapping
Workflow Gates are how ordered-process claims in a policy become executable.
| Policy claim | Workflow Gate boundary |
|---|---|
| The agent is read-only | Stages expose only read tools and terminal states block later writes |
| The agent can write only after reading approved context | file_read(...) entry or exit conditions enforce read-before-write |
| The agent must verify before review | command_matches(...), exec(...), or MCP result evidence blocks stage advance until verification exists |
| The agent needs human approval before a critical transition | approval pauses the stage boundary until approval evidence exists |
| The agent must prove conformance later | Workflow snapshots record active stage, completed stages, block reason, approval state, and last evidence |
Read-only policies often use simple read-only stages and terminal stops. Bounded-action policies usually need read/write stages plus evidence-before-stage-advance and approval-before-critical-transition. Broad-action policies need stricter stage allowlists, more approvals, and closer audit review.
Real Workflow YAML
apiVersion: edictum/v1
kind: Workflow
metadata:
name: coding-review
description: "Read context, implement, verify, review, then stop"
stages:
- id: read-context
tools: [Read]
exit:
- condition: file_read("/workspace/TASK.md")
message: Read TASK.md before coding
- id: implement
entry:
- condition: stage_complete("read-context")
tools: [Read, Edit, Write, MultiEdit, Bash]
checks:
- command_not_matches: "(?:^|(?:&&|\\|\\||;|\\n)\\s*)git\\s+(add|commit|push)\\b"
message: Do not commit or push before review
- id: verify
entry:
- condition: stage_complete("implement")
tools: [Bash, "mcp__ci__*"]
checks:
- command_matches: "^pnpm\\s+build$"
message: Run pnpm build before review
exit:
- condition: exec("pnpm build", exit_code=0)
message: pnpm build must pass
- condition: mcp_result_matches("mcp__ci__status", "outcome", "passing")
message: CI status must be passing
- id: review
entry:
- condition: stage_complete("verify")
tools: [Read, Bash]
approval:
message: Human review complete?
- id: done
entry:
- condition: stage_complete("review")
terminal: trueSupported Conditions
| Condition | Where it fits | What it checks |
|---|---|---|
stage_complete("stage-id") | entry, exit | Whether an earlier stage already completed |
file_read("path") | entry, exit | Whether read evidence recorded that path |
approval() / approval("stage-id") | entry, exit | Whether approval was recorded |
command_matches("regex") | entry, exit | Whether command evidence matches the regex |
command_not_matches("regex") | entry, exit | Whether command evidence does not match the regex |
exec("cmd", exit_code=0) | entry, exit | Whether a trusted command exits with the expected code |
mcp_result_matches("tool", "field", "value") | entry, exit | Whether structured MCP result evidence matches one exact field/value pair |
Tool Patterns And Terminal Stages
Workflow tools entries are authoritative.
Exact names work:
tools: [Read, Edit, Bash]Glob patterns work too:
tools: ["mcp__ci__*", Read]Terminal stages are the stop line:
- id: done
terminal: true- a terminal stage must be the last stage
- a terminal stage with no
toolsblocks every later tool call - a terminal stage with
toolsstill enforces that allowlist, but never advances past itself
SDK Status
Workflow Gates are documented across Python, TypeScript, and Go. That does not mean every helper, condition evaluator, adapter hook, or release version has identical behavior.
| SDK | Documented workflow attachment | Parity note |
|---|---|---|
| Python | workflow_path, workflow_content, or a prebuilt WorkflowRuntime | Reference docs path. Check the installed version before relying on a specific condition. |
| TypeScript | WorkflowRuntime with loadWorkflowString() | Documented runtime path. Do not assume every Python helper exists in TypeScript. |
| Go | workflow.Load() plus guard.WithWorkflowRuntime() | Documented runtime path. Gate uses Go, but SDK and Gate behavior should still be verified per release. |
Cross-SDK Setup
Python
from edictum import Edictum
guard = Edictum.from_yaml(
"rules.yaml",
workflow_path="workflow.yaml",
workflow_exec_evaluator_enabled=True, # only if workflow uses exec(...)
)TypeScript
import { Edictum, WorkflowRuntime, loadWorkflowString } from '@edictum/core'
const workflowRuntime = new WorkflowRuntime(loadWorkflowString(workflowYaml), {
execEvaluatorEnabled: true,
})
const guard = Edictum.fromYaml('rules.yaml', { workflowRuntime })Go
import (
"github.com/edictum-ai/edictum-go/guard"
"github.com/edictum-ai/edictum-go/workflow"
)
definition, err := workflow.Load("workflow.yaml")
if err != nil {
panic(err)
}
runtime, err := workflow.NewRuntime(definition, workflow.WithExecEvaluatorEnabled())
if err != nil {
panic(err)
}
g, err := guard.FromYAML("rules.yaml", guard.WithWorkflowRuntime(runtime))
if err != nil {
panic(err)
}Evidence Model
What the runtime records automatically:
- successful
Readcalls add file-read evidence - successful
Bashcalls add command evidence - approved stages add approval evidence
- MCP-backed integrations can add structured result evidence
The workflow snapshot emitted in audit events includes:
active_stagecompleted_stagesblocked_reasonpending_approvallast_blocked_actionlast_recorded_evidence
These snapshots are the audit trail of behavioral conformance for the workflow side of the runtime policy.
Reference Stack Split
The current model is:
- rulesets can come from
edictum-api - workflow YAML is still attached locally in the SDK runtime
- approvals, events, audit, keys, and SSE can flow through the optional reference API/app stack
That is why rulesets and workflows are separate documents today.
Related
Last updated on