
Building an Agent Control Plane (Before the Enterprise ones arrive!
- Mark Kendall
- 5 days ago
- 4 min read
Building an Agent Control Plane (Before the
Enterprise ones arrive!
Most engineers are being introduced to “AI platforms” and “control planes” through polished demos and enterprise tooling that doesn’t exist yet in their day-to-day work.
That’s a problem.
Because control planes are not magic.
They’re architecture patterns — and you can understand (and even build) them today, inside your own repos and clusters, with tools you already control.
This article walks through a practical, developer-owned approach to building a lightweight agent control plane using:
Git webhooks
Python microservices
Large Language Models (LLMs)
Explicit reasoning flows
No vendor dependency.
No central platform required.
No enterprise permissions needed (for a first pass).
Just solid architectural thinking.
The Mental Shift: From Pipelines to Control Planes
Traditional pipelines work like this:
Code → Pipeline → Result
A control plane works differently:
Event → Reason → Decide → Act
That distinction matters.
Instead of hardcoding behavior into YAML or scripts, you introduce a decision layer that can:
Inspect context
Apply policy
Choose what to do — or not do
That’s what an agent really is.
The Simplest Control Plane You Can Build
At a minimum, a control plane has four responsibilities:
Ingest events
Route based on policy
Execute reasoning
Produce a decision or recommendation
Here’s what that looks like in practice.
This entire system can live inside your own AWS cluster or Kubernetes environment.
Step 1: Events Are the Trigger (Not Humans)
Modern Git systems already emit events:
Pull request opened
Merge request updated
Code pushed
Pipeline failed
You don’t write this infrastructure.
You subscribe to it.
Git platforms send these events via webhooks — HTTP POSTs to an endpoint you control.
That endpoint becomes the front door of your control plane.
Step 2: A Python Web Service Is Your Control Plane
At its simplest, your control plane is just a Python service.
Example using FastAPI:
from fastapi import FastAPI, Request
app = FastAPI()
@app.post("/events/git")
async def handle_event(request: Request):
payload = await request.json()
event = normalize_event(payload)
decision = route_and_reason(event)
return {"status": "accepted", "decision": decision}
Key rule:
The webhook handler should do almost nothing.
It should:
Validate the request
Normalize the event
Hand it off to internal logic
No business logic here.
Step 3: Normalize Events Early
Raw webhook payloads are noisy.
Your control plane should reduce them to engineering-relevant facts:
def normalize_event(payload):
return {
"event_type": payload["object_kind"],
"repo": payload["project"]["path_with_namespace"],
"author": payload["user"]["username"],
"changed_lines": estimate_diff(payload),
"labels": extract_labels(payload)
}
This is where control planes differ from pipelines:
Pipelines react blindly
Control planes reason over meaning
Step 4: Policy Before Intelligence
Before you invoke any AI model, ask:
Is this repo even in scope?
Is this event relevant?
Are we in advisory or enforcement mode?
def policy_allows(event):
return (
event["changed_lines"] > 500
and "refactor" in event["labels"]
)
This protects you from:
Cost explosions
Noise
Accidental automation
LLMs should be gated, not default.
Step 5: Agents Are Reasoning Units, Not Bots
An agent is not a chat interface.
An agent is a structured reasoning flow:
Gather context
Apply constraints
Produce a decision
Explain the decision
Example agent structure:
class RefactorAgent:
def init(self, llm):
self.llm = llm
def run(self, context):
prompt = f"""
You are a senior software architect.
Context:
{context}
Rules:
- Do not change business logic
- Prefer small refactors
- Explain every decision
Task:
Provide refactoring recommendations.
"""
return self.llm.invoke(prompt)
Notice what’s missing:
No autonomy
No looping
No “thinking forever”
Agents serve engineering judgment, not curiosity.
Step 6: LLMs Are a Component, Not the System
The LLM is just one part of the control plane.
It should:
Receive structured input
Operate under explicit rules
Return bounded output
Your system should never depend on:
Memory inside the model
Chat history
Implicit behavior
Everything important lives outside the model.
Step 7: Decisions, Not Actions (At First)
For early implementations, the safest output is advice, not mutation.
Examples:
PR comments
Architecture reports
Lint summaries
Refactor recommendations
This avoids:
Enterprise permissions
Security reviews
Irreversible changes
And it still delivers real value.
Step 8: Why This Matters Before Enterprise Control Planes Arrive
Enterprise platforms will eventually give you:
Central orchestration
GUIs
Approval workflows
Governance layers
But those platforms will assume you already understand:
Event-driven systems
Policy-based routing
Agent reasoning flows
Control-plane separation
This approach gives you that understanding now.
What You Gain as an Architect
By building (or even just understanding) this model, you gain:
Control-plane literacy
Better pipeline design
Cleaner automation boundaries
Stronger conversations with platform teams
Real leverage inside your own repos
You’re no longer waiting for tools.
You’re reasoning at the same level they are.
Final Thought
Control planes are not products.
They’re patterns.
If you can:
Receive events
Reason over context
Make explicit decisions
You’re already building one.

Comments