{"id":48737040,"url":"https://github.com/laa-software-engineering/agentic-control-plane","last_synced_at":"2026-06-07T05:01:12.008Z","repository":{"id":350783641,"uuid":"1207423143","full_name":"LAA-Software-Engineering/agentic-control-plane","owner":"LAA-Software-Engineering","description":"Terraform-style plan/apply for agent systems: versioned YAML for agents, tools, workflows, and policies; local-first SQLite state; MCP \u0026 HTTP tools; structured traces.","archived":false,"fork":false,"pushed_at":"2026-06-02T05:51:16.000Z","size":504,"stargazers_count":4,"open_issues_count":13,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-02T06:08:35.150Z","etag":null,"topics":["agents","ai-agents","cli","declarative","gitops","golang","llm","mcp","model-context-protocol","orchestration","policy-as-code","sqlite","workflow","yaml"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LAA-Software-Engineering.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-10T23:35:30.000Z","updated_at":"2026-06-02T05:48:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/LAA-Software-Engineering/agentic-control-plane","commit_stats":null,"previous_names":["laa-software-engineering/agentic-control-plane"],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/LAA-Software-Engineering/agentic-control-plane","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LAA-Software-Engineering%2Fagentic-control-plane","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LAA-Software-Engineering%2Fagentic-control-plane/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LAA-Software-Engineering%2Fagentic-control-plane/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LAA-Software-Engineering%2Fagentic-control-plane/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LAA-Software-Engineering","download_url":"https://codeload.github.com/LAA-Software-Engineering/agentic-control-plane/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LAA-Software-Engineering%2Fagentic-control-plane/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33895175,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agents","ai-agents","cli","declarative","gitops","golang","llm","mcp","model-context-protocol","orchestration","policy-as-code","sqlite","workflow","yaml"],"created_at":"2026-04-12T05:06:29.058Z","updated_at":"2026-06-04T08:00:55.536Z","avatar_url":"https://github.com/LAA-Software-Engineering.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Agentic Control Plane\n\n[![CI](https://github.com/LAA-Software-Engineering/agentic-control-plane/actions/workflows/ci.yml/badge.svg)](https://github.com/LAA-Software-Engineering/agentic-control-plane/actions/workflows/ci.yml)\n[![Release](https://github.com/LAA-Software-Engineering/agentic-control-plane/actions/workflows/release.yml/badge.svg)](https://github.com/LAA-Software-Engineering/agentic-control-plane/actions/workflows/release.yml)\n[![Go 1.22+](https://img.shields.io/badge/Go-1.22+-00ADD8?logo=go)](https://go.dev/dl/)\n[![License: Apache-2.0](https://img.shields.io/badge/License-Apache-yellow.svg)](LICENSE)\n[![Go Reference](https://pkg.go.dev/badge/github.com/LAA-Software-Engineering/agentic-control-plane.svg)](https://pkg.go.dev/github.com/LAA-Software-Engineering/agentic-control-plane)\n\n\u003cimg width=\"1082\" height=\"625\" alt=\"image\" src=\"https://github.com/user-attachments/assets/bbcc8d7f-6031-4f65-b5c9-1d5cd6424e91\" /\u003e\n\n\n**Declarative YAML for agents, tools, workflows, and policies — with a Terraform-style plan/apply loop, local SQLite state, and execution traces.**\n\nThis is **not** another opaque agent framework. It is a **control plane**: you describe the *desired shape* of your agent system in versioned resources, then **validate**, **plan**, **apply**, **run**, and **inspect logs** the same way you would operate real infrastructure.\n\n---\n\n## Why this exists\n\nMost agent stacks today bury prompts, tool wiring, and permissions in application code. That makes it hard to answer basic operational questions: *Is this config valid? What changed? What are we about to deploy? What actually ran? Did policy allow it?*\n\n**Agentic Control Plane** pushes those concerns into **explicit YAML** (Kubernetes-like resources) and a small **Go CLI** (`agentctl`), so teams can:\n\n- Review diffs and plans before changes land  \n- Track **deployment state** separately from **runtime traces**  \n- Enforce **policies** (budgets, approvals, tool rules) at execution time  \n- Stay **local-first** while the architecture leaves room for a future remote control plane  \n\nThe full product vision, YAML spec v0, and architecture are documented in [**`docs/DESIGN_DOC.md`**](docs/DESIGN_DOC.md).\n\n**Featured walkthrough:** declarative PR review with a **policy-blocked** (simulated) GitHub comment — no API keys required — in [**`examples/pr-review-demo/README.md`**](examples/pr-review-demo/README.md). For the **live GitHub read/write path** with a **mock** reviewer (CI-friendly, no API keys), see [**`examples/pr-review-github/README.md`**](examples/pr-review-github/README.md). For the **same flow with OpenAI `gpt-4o-mini`** plus **GitHub Actions** (PR workflow posts a review comment), see [**`examples/pr-review-github-actions/README.md`**](examples/pr-review-github-actions/README.md) ( **[`.github/workflows/agentctl-pr-review.yml`](.github/workflows/agentctl-pr-review.yml)**; optional manual **`owner`/`repo`/`number`**: **[`.github/workflows/agentctl-pr-review-publish.yml`](.github/workflows/agentctl-pr-review-publish.yml)**).\n\n---\n\n## Mental model\n\n| Idea | Analogy |\n|------|---------|\n| Desired resources in Git | **GitOps** |\n| `plan` / `apply` / drift | **Terraform** |\n| Typed resources (`Project`, `Workflow`, `Policy`, …) | **Kubernetes**-style API |\n| Tool and IO contracts | **OpenAPI**-style explicitness |\n\n---\n\n## Features (MVP today)\n\n- **`agentctl init`** — scaffold `project.yaml`, policies, tools, and a sample workflow  \n- **`agentctl validate`** — load project, apply **project defaults** (`spec.defaults`), then **environment overlays** (`-e` / `--env`, `Environment` resources §7.6), then validate graph, schemas, and references; runs **policy lint** (ungated sensitive tools, invalid HITL config, etc.) as **advisory** output — use **`--strict`** to exit **2** on high-severity lint findings (fail-closed safety metadata still gates at **run** even when lint passes)  \n- **`agentctl plan`** — diff desired graph vs SQLite **deployment** state; risk hints including policy lint; JSON/YAML output includes **`policyLint`** and a **`deploymentBaseline`** digest for the store snapshot  \n- **`agentctl apply`** — persist plan (TTY confirm or `--auto-approve` / `AGENTCTL_AUTO_APPROVE`); **optimistic concurrency** — if the deployment store changed after the plan snapshot (e.g. another process applied the same `--state` file while this run waited at the prompt), apply fails with **exit code 3**; re-run **plan** then **apply**  \n- **`agentctl run`** — execute a workflow locally; JSON Schema for inputs where configured; policy gates pause for **human-in-the-loop (HITL)** approval when a tool call requires it  \n- **`agentctl logs`** — read **trace events** from SQLite (`--run`, `--workflow`, or recent runs)  \n- **Tools** — **`native`**, **`http`**, **`mock`**, and **`mcp`** — MCP supports **stdio** (subprocess) or **streamable HTTP** (`spec.mcp.transport: http`, `url`, optional `headers` with `env:` tokens)  \n- **Project defaults** — besides **`model`** and **`policy`**, optional **`runtime`** flows to **`spec.runtime`** on agents/workflows when omitted (MVP: **`local`** or unset; see spec validation)  \n- **Output** — table, JSON, or YAML (`-o` / `--output`)  \n- **State** — single SQLite file (default `.agentic/state.db` under the project root; override with `--state`)  \n- **Tests** — unit/integration coverage, golden CLI output tests, end-to-end `init → … → logs` in `test/integration`  \n\nSee **section 18 (MVP)** and **section 19 (End Goal)** in [`docs/DESIGN_DOC.md`](docs/DESIGN_DOC.md) for the full included/excluded list.\n\n---\n\n## Quick start\n\n### Prerequisites\n\n- **From source:** [Go 1.22+](https://go.dev/dl/)\n- **From a [release binary](#prebuilt-binaries):** no Go toolchain; put `agentctl` (or `agentctl.exe`) on your `PATH` after extracting the archive\n\n### Build\n\n```bash\ngit clone https://github.com/LAA-Software-Engineering/agentic-control-plane.git\ncd agentic-control-plane\nmake build   # writes bin/agentctl\n```\n\nOr: `make install` / `go install ./cmd/agentctl` (honours `GOBIN` / `GOPATH/bin`; ensure that directory is on `PATH`).\n\n### Prebuilt binaries\n\n[GitHub Releases](https://github.com/LAA-Software-Engineering/agentic-control-plane/releases) ship **`agentctl`** for common platforms (`.tar.gz` on Linux/macOS, `.zip` on Windows) plus **`SHA256SUMS.txt`**. Pick the archive that matches your machine, for example:\n\n| Platform | Asset suffix |\n|----------|----------------|\n| Linux x86_64 | `linux-amd64.tar.gz` |\n| Linux arm64 | `linux-arm64.tar.gz` |\n| macOS Intel | `darwin-amd64.tar.gz` |\n| macOS Apple Silicon | `darwin-arm64.tar.gz` |\n| Windows x86_64 | `windows-amd64.zip` (contains `agentctl.exe`) |\n\n`agentctl version` reports the release tag (e.g. `v0.1.4`).\n\nReleases are **created automatically** when changes land on **`main`**, using a **patch** semver bump over the latest `vMAJOR.MINOR.PATCH` tag (merges that only touch Markdown or the root `Makefile` do not trigger a release). To cut **minor** or **major** bumps on demand, run the [**Release** workflow](https://github.com/LAA-Software-Engineering/agentic-control-plane/actions/workflows/release.yml) manually (**Actions → Release → Run workflow**) and choose the bump type.\n\n### Create a project and run the loop\n\nFrom the repo root (or anywhere):\n\n```bash\nagentctl init my-agent-system\nagentctl validate --project my-agent-system\nagentctl plan   --project my-agent-system\nagentctl apply  --project my-agent-system --auto-approve\nagentctl run    workflow/hello --project my-agent-system\nagentctl logs   --project my-agent-system --workflow hello\nagentctl inspect --web --project my-agent-system   # read-only local UI on http://127.0.0.1:8787\n```\n\n`inspect --web` binds to **localhost only** and opens the state DB read-only. Avoid running it while `agentctl run` is writing the same SQLite file (you may see `database is locked` without WAL); use it when runs are idle or on a copy of the DB.\n\n### Example `project.yaml`\n\nThe project root is a **`Project`** resource: `apiVersion`, `kind`, `metadata.name`, and **`spec.imports`** listing other YAML files (policies, tools, workflows). After **`agentctl init my-agent-system`**, `my-agent-system/project.yaml` looks like this:\n\n```yaml\napiVersion: agentic.dev/v0\nkind: Project\nmetadata:\n  name: my-agent-system\nspec:\n  imports:\n    - ./policies/default.yaml\n    - ./tools/helper.yaml\n    - ./workflows/hello.yaml\n  defaults:\n    policy: default\n    model: openai/gpt-4o-mini\n    runtime: local\n  providers:\n    models:\n      openai:\n        type: openai\n        apiKeyFrom: env:OPENAI_API_KEY\n      # Optional: Claude via Messages API (set ANTHROPIC_API_KEY and use e.g. defaults.model: anthropic/claude-sonnet-4-20250514)\n      # anthropic:\n      #   type: anthropic\n      #   apiKeyFrom: env:ANTHROPIC_API_KEY\n```\n\nField-by-field rules, extra kinds, env overlays, MCP HTTP tools, and **`defaults.runtime`** are in [`docs/DESIGN_DOC.md`](docs/DESIGN_DOC.md). See [`docs/EXAMPLES.md`](docs/EXAMPLES.md) for Anthropic fragments, MCP over HTTP, and structured-output notes.\n\nNotes:\n\n- **`init`** creates `my-agent-system/` with `apiVersion: agentic.dev/v0` resources and a **`hello`** workflow (native `echo` tool only — **no network**).  \n- **`apply`** in non-interactive environments needs **`--auto-approve`** or **`AGENTCTL_AUTO_APPROVE=1`**.  \n- **`run`** HITL: gated tool calls exit with **`Status: interrupted`** (exit **0**). Resume with **`--resume \u003crun-id\u003e --decision approve|reject|edit|switch`** (use **`--decision-edit-json`** / **`--decision-switch-target`** when needed), or skip prompts with **`--auto-approve`** / **`AGENTCTL_AUTO_APPROVE=1`**. Pre-approve a specific call with repeated **`--approve \u003cuses\u003e`**. Set **`AGENTCTL_HITL_ACTOR`** to attribute decisions in trace logs.  \n- **`Policy.spec.hitl.interruptOn`** keys are **Tool metadata.name** values; they configure review options (edit rules, switch targets) for calls already gated by **`approvals.requiredFor`** or safety metadata — they do not gate tools on their own.  \n- **`run`** stores traces in the **same** SQLite file used for plan/apply (default **`.agentic/state.db`** under `--project`). Optional OTLP export (`spec.telemetry`, off by default) is additive only — see [`docs/OTEL.md`](docs/OTEL.md). When enabled you need `serviceName` plus either `consoleExport: true` or an `endpoint` (`https://…` or `env:VAR`, e.g. `env:OTEL_EXPORTER_OTLP_ENDPOINT`). Export that variable before `run` if you use `env:`; if it is missing or the collector is unreachable, `agentctl` logs a warning, skips OTLP, and the workflow still completes (SQLite traces unchanged).  \n- If **`spec.traces.retentionDays`** is a positive integer, runs older than that many **UTC calendar days** (by `runs.started_at`) are deleted lazily on **`run`** and **`logs`** (child trace rows cascade). Unset or non-positive means no pruning.  \n- Use **`logs --run \u003cid\u003e`** after a run if you want a single run’s trace (IDs are printed by **`run`**).  \n\n### Global flags (common)\n\n| Flag | Purpose |\n|------|---------|\n| `--project \u003cpath\u003e` | Project root (default `.`) |\n| `--state \u003cpath\u003e` | SQLite file override |\n| `-e` / `--env` | Environment overlay name |\n| `-o` / `--output` | `table`, `json`, or `yaml` |\n| `--no-color` | ASCII-friendly validate output |\n\nExit codes are summarized in **section 11.2** of [`docs/DESIGN_DOC.md`](docs/DESIGN_DOC.md) (`0` success, `2` validation, **`3` plan/apply conflict** when deployment state changed after `plan`, `4` execution, `5` policy denial, …).\n\n---\n\n## Repository layout (high level)\n\n| Path | Role |\n|------|------|\n| `cmd/agentctl` | CLI entrypoint |\n| `internal/cli` | Cobra commands, flags, golden tests |\n| `internal/spec` | YAML types, normalize, validate |\n| `internal/project` | Load project + imports |\n| `internal/plan` | Planner and risk summary |\n| `internal/apply` | Apply plan to deployment store |\n| `internal/engine` | Workflow execution |\n| `internal/policy` | Policy evaluation |\n| `internal/state/sqlite` | SQLite deployment + runtime/trace tables |\n| `test/integration` | End-to-end CLI flow tests |\n| `docs/DESIGN_DOC.md` | Spec, CLI UX, architecture, roadmap |\n| `docs/GITHUB_ACTIONS.md` | Running **`agentctl`** from GitHub Actions (tokens, exit code **5**, template path) |\n| `examples/pr-review-github-actions/` | Full **`gpt-4o-mini`** project; PR workflow **`.github/workflows/agentctl-pr-review.yml`**; optional publish **`.github/workflows/agentctl-pr-review-publish.yml`** |\n\n---\n\n## Development\n\n**`make`** defaults to **`help`**, which lists targets; the table below mirrors the [`Makefile`](Makefile) (`##` comments and recipes).\n\n| Target | What it does |\n|--------|----------------|\n| `help` | Show usage and target list (default goal) |\n| `all` | `fmt` → `vet` → `test` → `build` (handy before a push) |\n| `build` | `go build` → `bin/agentctl` |\n| `install` | `go install ./cmd/agentctl` (`-trimpath`; uses `GOBIN` / `GOPATH/bin`) |\n| `clean` | Remove `bin/` and `coverage.out` |\n| `fmt` | `go fmt ./...` |\n| `verify-fmt` | Fail if `gofmt -l` would list files (matches CI-style formatting check) |\n| `vet` | `go vet ./...` |\n| `test` | `go test ./... -race` |\n| `test-coverage` | Tests with `-coverprofile=coverage.out` and a one-line `go tool cover -func` summary |\n| `check` | `vet` + `test` only (no formatting writes) |\n| `ci` | `verify-fmt` + `vet` + `test` (no build) |\n\nCI (`.github/workflows/ci.yml`) runs **Linux, macOS, and Windows** on Go **1.22.x**, plus **Go 1.23.x** on Linux, with **race** and **shuffle** enabled (workflow steps are defined in YAML, not via `make ci`).\n\n### Updating CLI golden files\n\nWhen table output is intentionally changed:\n\n```bash\nGO_UPDATE_GOLDEN=1 go test ./internal/cli/... -run TestGolden_\n```\n\n---\n\n## Roadmap\n\n### Near term (MVP hardening)\n\nRecent landings already cover much of “hardening”: **plan/apply optimistic concurrency** (exit **3** when deployment state drifts), **MCP** over **streamable HTTP** as well as stdio, **trace retention** (`spec.traces.retentionDays`), **`defaults.runtime`** / **`spec.runtime`** (MVP `local`), and clearer **defaults vs environment overlay** documentation. What is still open for near-term polish:\n\n- More **`diff` / drift** UX where the design doc calls for it (beyond today’s resource-level diff)  \n- Richer **`logs`** filtering (see sections **10.2** and **17.3** in `docs/DESIGN_DOC.md`); **`inspect --web`** covers read-only run/state browsing ([#109](https://github.com/LAA-Software-Engineering/agentic-control-plane/issues/109))  \n- **`agentctl test`**-style workflow fixtures (**stretch** per design doc)  \n\n### Post-MVP (from design doc section 19)\n\n- Modules/registry, remote shared state, reconciliation controllers  \n- Parallel steps, subworkflows, schedules/events  \n- Stronger drift semantics and multi-runtime targets  \n- Deeper approval workflows and multi-tenant controls  \n\nThe **recommended implementation phases** are outlined in **section 20** of [`docs/DESIGN_DOC.md`](docs/DESIGN_DOC.md).\n\n---\n\n## Documentation\n\n- **[`docs/DESIGN_DOC.md`](docs/DESIGN_DOC.md)** — design document v0 (problem statement, spec, CLI, engine, state model, testing strategy, MVP vs end state, section 23 recommendation).  \n- **[`examples/pr-review-demo/README.md`](examples/pr-review-demo/README.md)** — end-to-end demo: structured review output, traceable run, **approval-gated** write (`validate` → `plan` → `apply` → `run` → `logs`).\n- **[`docs/EXAMPLES.md`](docs/EXAMPLES.md)** — copy-paste YAML and CLI examples (`init`, mock vs OpenAI, workflows, environment overlays).  \n- **[`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md)** — Contributor Covenant 2.1; participation expectations and reporting.  \n- **License:** [MIT](LICENSE)  \n\n---\n\n## Contributing\n\nIssues and pull requests are welcome. See **[`CONTRIBUTING.md`](CONTRIBUTING.md)** for local setup, tests, golden updates, and pull request expectations.\n\n---\n\n\u003e **Local declarative agent systems with validate, plan, apply, run, and logs.**  \n\u003e *(Closing recommendation in [`docs/DESIGN_DOC.md`](docs/DESIGN_DOC.md), section 23.)*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaa-software-engineering%2Fagentic-control-plane","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flaa-software-engineering%2Fagentic-control-plane","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaa-software-engineering%2Fagentic-control-plane/lists"}