markov
Health Warn
- License — License: Apache-2.0
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Workflow engine for chaining agents with code; Codify turns the work that needs no judgment into native steps
Markov
A Go workflow engine for chaining agents with code. Declarative YAML workflows mix agent steps
(Claude Code), scripts, HTTP APIs and Kubernetes Jobs, with explicit state, rules, loops and
checkpoint/resume. Codify then progressively moves the work
that needs no judgment out of agent steps into native ones, one validated change at a time, and
leaves the judgment with an agent.
Why "Markov"?
A Markov chain is a system that transitions between states based on its current state. Markov workflows work the same way: gate steps evaluate rules against the current state, decide whether to continue or pause for explicit external input, and workflows can loop or recursively invoke themselves until the rules say to stop. The result is a declarative state machine where each iteration's next move depends only on the facts right now, not the history of how it got there.
Features
Steps
- Agent steps —
clauderuns a prompt or skill through the Claude Code CLI, with live transcripts, limits on turns, tokens, time and spend, and optional JSON-schema answers - Native steps —
shell_exec,script_exec,write_file,http_request(pagination, streamed SSE responses),k8s_job/k8s_job_wait(batch/v1Jobs directly, no Argo),ansible/ansible_playbook,prompt(interactive input), and OpenShell sandboxes - User-defined step types — compose reusable types from the primitives
- Data —
set_fact,assert, andload_artifactfor YAML, markdown and markdown tables from local files or K8s pods - Jev decisions — native Jev/Kev API steps, durable inline conditions, and decision-backed gate facts; see the Jev reference
Control flow
- Conditionals —
when:expressions - Fan-out / fan-in —
for_eachwith sliding-window concurrency (forks) and stable keys for resumable fan-outs - Loops —
repeat: bounded do-while loops over a sub-workflow (until,max); workflows can also call themselves - Rules and gates — named rules with salience-based priority (Grule); gate steps set facts and can pause durably for explicit resume input
- Failure handling —
ignore_errors,failed_when, and workflow-levelrescueandalwayshandlers, which also run after a cancelled run
State and visibility
- Checkpoint/resume — SQLite or Postgres state store; resume failed or paused runs from the last completed step
- Debugger — breakpoints (on steps and on loop iterations), stepping and expression evaluation over a JSON-lines control channel
- Callbacks — events to JSONL files, a live terminal view (
tty://), HTTP or gRPC
Evolving workflows
- Hot reload —
reload_workflowsteps, or a request over the control channel, swap the definition of a running workflow; new sub-workflow calls use it (explicit and opt-in with--allow-reload) - Codify — record a live run, let a retro agent move one job into native steps in a copy, replay the recording against it, and promote it when its outputs still match; strict and loose modes, agent steps you keep, iteration and spend limits
Safety and correctness
- Variable scoping — file-level vars are read-only globals, and a called workflow sees only what it declares and is passed
markov validate— checks structure, the variables each workflow can see, and that every template and expression parses- Secrets — secret vars and step outputs are masked in events and in stored state
- Output limits — steps stop reading output past a size limit (default 64MB)
Layout
- Single-file or directory workflows — one file per workflow, in subfolders named by their path (
workflows/tools/grep.yamlistools.grep) - Templates — Jinja2-compatible (pongo2) for params and expressions
Built with Markov
- markovd — web dashboard and HTTP API: trigger and schedule runs, and follow them live
- markov-harness — a minimal Claude Code-style coding agent written entirely as a Markov workflow: streaming replies, tools with approvals, memory and prompt caching
Documentation
Full documentation is available at docs/, including:
- Getting Started — install and run your first workflow
- Language Reference — complete YAML DSL schema
- Step Types — all built-in step types
- Guides — practical how-to guides
How is this different from X?
See docs/design/project-comparisons.md for detailed comparisons with Ansible, Argo Workflows, Jenkins, Tekton, Kestra, CrewAI, and LangGraph.
Install
Download a binary for Linux or macOS (amd64, arm64) from the releases,
unpack it and put markov on your PATH:
tar -xzf markov_<version>_<os>_<arch>.tar.gz markov && sudo mv markov /usr/local/bin/
Or build it with Go 1.25 or later:
go install github.com/vokramd/markov/cmd/markov@latest # or, from a clone: make build (bin/markov)
Quick Start
Nothing but markov is needed: no cluster, no agent.
git clone https://github.com/vokramd/markov && cd markov
markov validate examples/quickstart.yaml
markov run examples/quickstart.yaml --callback tty:// # fan-out, a loop, a branch, a report
cat quickstart-report.md
markov status <run-id> --steps # what ran, and how long each step took
examples/quickstart.yaml checks three services at once (for_each), repeats a
sub-workflow until it reports the cache is warm (repeat), runs a step only if it did (when), and writes a
report (write_file). Next:
- An agent step:
examples/claude.yamlasks Claude a question with enforced limits
(needs theclaudeCLI). - Codify:
markov codifymoves the work an agent step does that needs no
judgment into native steps. - Getting started: docs/getting-started.md.
Resume a failed or paused run with markov resume <run-id>, and draw a finished one with markov diagram <run-id>
(Mermaid).
On Kubernetes
k8s_job steps create batch/v1 Jobs directly, in the namespace you give:
markov run examples/k8s-job-test.yaml --namespace markov-test --verbose
Example
entrypoint: main
namespace: markov-test
forks: 2
vars:
greeting: "hello from markov"
items: ["alpha", "bravo", "charlie"]
step_types:
echo_job:
base: k8s_job
job:
image: alpine:3.19
command: ["/bin/sh", "-c"]
workflows:
- name: main
steps:
- name: hello
type: echo_job
params:
args: ["echo '{{ greeting }}'"]
- name: fan-out
for_each: "items"
as: item
workflow: per-item
vars:
value: "{{ item }}"
- name: per-item
vars:
value: null
steps:
- name: process
type: echo_job
params:
args: ["echo 'processing: {{ value }}'"]
CLI
| Command | |
|---|---|
markov run <file|dir> |
Run a workflow |
markov resume <run-id> |
Resume a failed or paused run |
markov validate <file|dir> |
Check a workflow without running it |
markov codify <dir> |
Progressively move agent work into native steps |
markov status <run-id>, markov list |
Inspect runs |
markov diagram <run-id> |
Mermaid diagram of a run |
markov schema |
The workflow format as JSON, for editors and agents |
Common run flags: --var key=value, --workflow name, --forks N, --state-store path-or-dsn,--callback url, --control stdin, --break workflow.step, --allow-reload, --verbose. See the
CLI reference for all of them.
Project Structure
cmd/markov/ CLI entrypoint
pkg/engine/ Workflow execution, gates, loops, debugger, reload, secrets
pkg/parser/ YAML parsing, validation, lint
pkg/executor/ Step executors (claude, shell_exec, script_exec, http_request, k8s_job, ...)
pkg/codify/ markov codify: recording proxy, retro agent, replay, judge
pkg/state/ Checkpoint store (SQLite, Postgres)
pkg/callback/ Event callbacks (jsonl, tty, http, grpc)
pkg/template/ Pongo2 template rendering and filters
pkg/jev/ Jev/Kev decision API client
pkg/openshell/ OpenShell sandbox steps (CLI and SDK transports)
examples/ Example workflow files
docs/ Documentation (reference, guides, design docs)
License
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found