Stage 7 · Master
Ops Agents & Automation Tools
Agent Architecture
Design planners, tool routers, memory stores, approval gates, and execution logs for operations agents.
What Is an Agent?
An agent is a system that plans, takes actions, observes results, and adapts. Unlike a simple prompt-response pipeline, an agent can loop — it decides what to do next based on what it just learned.
| Component | Role | Example |
|---|---|---|
| Planner | Decides what to do next | Analyze alert, choose investigation steps |
| Tool Router | Selects and calls the right tool | Query Prometheus, run kubectl |
| Memory | Stores context across steps | Conversation history, investigation state |
| Approval Gate | Requires human confirmation for risky actions | Approve before deleting resources |
| Execution Log | Records every action for audit | Log every API call and result |
The Planner
class AgentPlanner:
def __init__(self, tools, system_prompt):
self.tools = tools
self.system_prompt = system_prompt
def plan(self, goal, context):
"""Generate a plan for achieving the goal."""
tool_descriptions = "\n".join([
f"- {t.name}: {t.description}" for t in self.tools
])
response = openai.ChatCompletion.create(
model="gpt-4",
temperature=0.0,
messages=[
{"role": "system", "content": self.system_prompt},
{
"role": "user",
"content": f"""Goal: {goal}
Context: {context}
Available tools: {tool_descriptions}
Generate a step-by-step plan. For each step, specify:
- action: what to do
- tool: which tool to use (if any)
- expected_outcome: what you expect to learn"""
}
]
)
return parse_plan(response["choices"][0]["message"]["content"])The planner generates a sequence of steps. Each step specifies an action, a tool, and an expected outcome.
Tool Router
class ToolRouter:
def __init__(self, tools):
self.tools = {t.name: t for t in tools}
def select_tool(self, step, context):
"""Select the best tool for a step."""
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
temperature=0.0,
messages=[
{
"role": "system",
"content": f"""Select the best tool for this step.
Available tools: {list(self.tools.keys())}"""
},
{
"role": "user",
"content": f"Step: {step['action']}\nContext: {context}"
}
]
)
tool_name = response["choices"][0]["message"]["content"].strip()
return self.tools.get(tool_name)
def execute(self, tool, arguments):
"""Execute a tool with arguments."""
try:
result = tool.execute(**arguments)
return {"success": True, "result": result}
except Exception as e:
return {"success": False, "error": str(e)}The router uses the LLM to select the most appropriate tool based on the step description and available context.
Memory Store
class AgentMemory:
def __init__(self):
self.short_term = [] # Current investigation
self.long_term = {} # Cross-investigation knowledge
def add_observation(self, step, result):
"""Record what happened in a step."""
self.short_term.append({
"step": step,
"result": result,
"timestamp": time.time()
})
def get_context(self, max_steps=10):
"""Get recent context for the planner."""
recent = self.short_term[-max_steps:]
return "\n".join([
f"Step {i+1}: {s['step']['action']} -> {s['result']}"
for i, s in enumerate(recent)
])
def store_knowledge(self, key, value):
"""Store knowledge for future investigations."""
self.long_term[key] = value
def recall_knowledge(self, query):
"""Recall relevant knowledge from past investigations."""
# Search long-term memory for relevant entries
relevant = []
for key, value in self.long_term.items():
if query.lower() in key.lower():
relevant.append(value)
return relevantShort-term memory tracks the current investigation. Long-term memory stores patterns across investigations.
Approval Gate
class OpsAgent:
def __init__(self, planner, router, memory, approval_gate):
self.planner = planner
self.router = router
self.memory = memory
self.gate = approval_gate
def run(self, goal, channel_id):
"""Execute the agent loop."""
# Generate initial plan
plan = self.planner.plan(goal, self.memory.get_context())
for step in plan:
# Check if this step needs approval
approval = self.gate.check(step)
if approval.needs_approval:
approved = await_human_approval(channel_id, step)
if not approved:
self.memory.add_observation(step, "Skipped by user")
continue
# Select and execute tool
tool = self.router.select_tool(step, self.memory.get_context())
result = self.router.execute(tool, step["arguments"])
# Record result
self.memory.add_observation(step, result)
# Re-plan if needed
if not result["success"]:
plan = self.planner.plan(goal, self.memory.get_context())
break
return self.memory.get_context()The agent loops through the plan, executing steps and re-planning when something goes wrong.
Start with a single-step agent that takes one action. Add complexity only when the simple version proves insufficient. Complex agents are harder to debug and more likely to fail.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.