AI Agent Zero to Hero: Day 3 – Production-Ready Kubernetes Investigation Agent with Tool Calling
This chapter covers transforming a basic, static log-reading Kubernetes investigation agent into an autonomous, production-ready diagnostic agent. By leveraging Tool Calling (Function Calling) alongside the Google Agent Development Kit (ADK) and Agent CLI, we enable an AI agent to directly query live Kubernetes cluster APIs, execute diagnostic steps dynamically, and return structured root-cause reports with verifiable evidence.
1. The Production Gap: Passive Ingestion vs. Autonomous Investigation
In Day 2, we constructed a static Kubernetes investigation agent. While functional, that architecture suffered from a fundamental operational limitation: passive log ingestion.
In a production Site Reliability Engineering (SRE) environment, passive ingestion introduces severe friction:
- Manual Overhead: Human operators must locate the specific pod, identify which container failed, and manually pull log snippets.
- Missing Context: A log file alone rarely provides the full picture. Diagnosing complex failures requires inspecting Kubernetes API events, replica set rollouts, node statuses, and historical spec revisions.
- Delayed Time-to-Resolution (TTR): Static analysis forces an iterative, back-and-forth manual workflow between the engineer and the cluster.
To bridge this gap for production environments, the agent must transition to autonomous active investigation:
2. Core Mental Model: Tool & Function Calling
Large Language Models (LLMs) are strictly text-to-text transformer engines. They operate by predicting the next most probable token based on their training weights and context window. An LLM cannot natively establish TCP connections, execute HTTP calls to a Kubernetes API server, or execute local shell scripts.
Real-Life Analogy: The SRE Architect and the Field Engineer
Real-Life Analogy
Imagine an SRE Lead (the LLM) who possesses complete theoretical knowledge of all database and container failure modes, but works inside a soundproof control room with zero direct physical or network access to the server racks.
To diagnose a issue, the SRE Lead relies on a Field Engineer (the Tool Interface) stationed in the data center.
- The Lead hands the Engineer a specific instruction: "Run
kubectl get events -n defaultand read the output back to me."- The Engineer runs to the cluster, executes the exact command, translates the raw response into a standardized structured form (a JSON payload), and hands it back through the slot.
- The Lead reads the data, synthesizes the problem, and issues the next diagnostic command or delivers a final post-mortem report.
LLM Reasoning Engine (SRE Lead)
|
| 1. Formulates Intent & Generates Tool Call Request (JSON)
v
Agent Framework / Execution Runtime (Field Engineer Interface)
|
| 2. Invokes Python SDK / Kubernetes Client API
v
Target Environment (Kubernetes API Server / Cluster)
|
| 3. Returns Raw Cluster Payload (Logs, Events, Specs)
v
Agent Framework / Execution Runtime
|
| 4. Formats Raw Payload into LLM Schema
v
LLM Context Window (Synthesizes Data & Decides Next Step)
In Python-based agentic architectures, a Tool is a structured Python function equipped with a standard interface, input argument schemas (often powered by Pydantic or Google ADK tool declarations), and clean JSON return signatures that the LLM can easily evaluate.
3. Tool Development Workflow with Google ADK & Agent CLI
Building custom tools from scratch can require extensive boilerplate code to handle schema validation, dual-mode execution (local CLI vs. remote deployment), and framework binding. By coupling Agent CLI with the Google Agent Development Kit (ADK), we can generate and wire production-ready tools using declarative natural language instructions.
The Kubernetes Client Integration
Under the hood, all generated tools interface with the cluster using the official kubernetes Python SDK (kubernetes.client), executing authenticated API calls through standard kubeconfig contexts.
4. Designing the Diagnostic Toolsuite
To grant our agent full investigation capabilities, we implement three core diagnostic tools inside tools.py and register them within agents.py.
Tool 1: Container Log Extraction (get_pod_logs)
This tool replaces passive, static log files. It queries the Kubernetes Core API (CoreV1Api) to pull stdout and stderr streams directly from a target pod container.
# tools.py - Container Log Tool Definition
from google.genai import types
from kubernetes import client, config
def get_pod_logs(pod_name: str, namespace: str = "default", container: str = None) -> str:
"""Fetches log output from a specific container within a Kubernetes pod.
Args:
pod_name: Name of the target pod.
namespace: Kubernetes namespace (defaults to 'default').
container: Specific container name if pod has multiple containers.
Returns:
JSON/Text string containing log entries or formatted error messages.
"""
try:
config.load_kube_config()
v1 = client.CoreV1Api()
logs = v1.read_namespaced_pod_log(
name=pod_name,
namespace=namespace,
container=container if container else None,
tail_lines=100 # Cap context size to mitigate token saturation
)
return logs if logs else "No logs returned from pod container."
except client.exceptions.ApiException as e:
return f"Kubernetes API Error while fetching logs: {str(e)}"
Tool 2: Lifecycle Event Telemetry (get_pod_events)
Pods frequently crash due to infrastructure or scheduling failures (e.g., OOMKilled, ImagePullBackOff, FailedScheduling) that leave no trace inside container application logs. get_pod_events queries cluster events associated with the pod resource object.
# tools.py - Pod Events Tool Definition
def get_pod_events(pod_name: str, namespace: str = "default") -> str:
"""Retrieves cluster life-cycle events related to a target pod.
Args:
pod_name: Name of the target pod.
namespace: Kubernetes namespace.
Returns:
Formatted summary of recent cluster events for the object.
"""
try:
config.load_kube_config()
v1 = client.CoreV1Api()
field_selector = f"involvedObject.name={pod_name},involvedObject.kind=Pod"
events = v1.list_namespaced_event(namespace=namespace, field_selector=field_selector)
if not events.items:
return f"No recent events found for pod {pod_name} in namespace {namespace}."
event_summary = []
for event in events.items:
event_summary.append(
f"[{event.last_timestamp}] Type: {event.type} | Reason: {event.reason} | Message: {event.message}"
)
return "\n".join(event_summary)
except client.exceptions.ApiException as e:
return f"Kubernetes API Error while fetching events: {str(e)}"
Tool 3: Deployment Revision Analysis (get_deployment_history)
Application failures are frequently caused by recent changes, such as updated image tags, misconfigured environment variables, or resource limit tweaks. This tool inspects deployment revisions and ReplicaSet configurations.
# tools.py - Deployment History Tool Definition
def get_deployment_history(deployment_name: str, namespace: str = "default") -> str:
"""Analyzes recent spec changes, rollout revisions, and image configurations for a deployment.
Args:
deployment_name: Name of the deployment.
namespace: Target namespace.
Returns:
Structured summary of deployment revisions and current spec settings.
"""
try:
config.load_kube_config()
apps_v1 = client.AppsV1Api()
deployment = apps_v1.read_namespaced_deployment(name=deployment_name, namespace=namespace)
spec = deployment.spec
containers = spec.template.spec.containers
images = [c.image for c in containers]
replicas = spec.replicas
return (
f"Deployment: {deployment_name}\n"
f"Replicas Target: {replicas}\n"
f"Configured Containers & Images: {images}\n"
f"Strategy: {spec.strategy.type}\n"
)
except client.exceptions.ApiException as e:
return f"Kubernetes API Error while fetching deployment history: {str(e)}"
5. Declarative Agent Integration
Once declared in tools.py, these tools are registered inside agents.py using the Google Agent Development Kit bindings.
# agents.py - Multi-Tool Agent Orchestration Schema
from google.genai import types
from tools import get_pod_logs, get_pod_events, get_deployment_history
# Configuration binding tools into the LLM Reasoning Engine
k8s_investigation_agent = types.AgentConfig(
name="production_k8s_investigator",
model="gemini-2.5-pro",
system_instruction=(
"You are an expert SRE and Kubernetes troubleshooting agent. "
"Your task is to autonomously investigate pod failures by systematically calling tools. "
"Always cross-reference events, deployment configurations, and logs before reaching a final verdict."
),
tools=[
get_pod_logs,
get_pod_events,
get_deployment_history
]
)
6. Real-World Investigation Flow
The diagram below illustrates how the self-investigating agent processes a request from initial user prompt to final diagnostic report.
7. Diagnostic Tool Reference & Comparison
The table below outlines the core attributes, targets, and diagnostic responsibilities of each tool in the agent's toolsuite.
8. Real-World Fault Simulation & Live Trace Verification
To validate our autonomous agent, we simulate a realistic production deployment failure on a live Kubernetes cluster using an invalid container image reference.
Step 1: Injecting the Fault Scenario
In the terminal, create a broken deployment using a non-existent container tag:
# Create deployment referencing an unresolvable Docker image tag
kubectl create deployment nginx-export --image=nginx:nonexistent-tag-abc123
# Observe pod state moving into image pull failure status
kubectl get pods -w
Cluster Output:
NAME READY STATUS RESTARTS AGE
nginx-export-74d475bf7c-x89p2 0/1 ImagePullBackOff 0 18s
Step 2: Running the Autonomous Agent
Execute the agent using the natural language execution command:
agent_cli run "Identify nginx-export pod failure in the default namespace"
Step 3: Agent Tool Execution Trace
The CLI displays the execution trace as the agent autonomously runs tools to diagnose the cluster state:
[INFO] Agent Prompt Received: "Identify nginx-export pod failure in the default namespace"
[AGENT THOUGHT]: The user wants me to identify why the pod nginx-export is failing. First, I should fetch the pod events to see life-cycle issues.
[TOOL CALL 1]: get_pod_events(pod_name="nginx-export-74d475bf7c-x89p2", namespace="default")
[TOOL RESULT]:
[2026-03-30T10:14:02Z] Type: Warning | Reason: Failed | Message: Failed to pull image "nginx:nonexistent-tag-abc123": rpc error: code = NotFound desc = failed to pull and unpack image...
[2026-03-30T10:14:03Z] Type: Warning | Reason: Failed | Message: Error: ErrImagePull
[2026-03-30T10:14:15Z] Type: Normal | Reason: BackOff | Message: Back-off pulling image "nginx:nonexistent-tag-abc123"
[AGENT THOUGHT]: The events show image pull failure. Let me verify the deployment history to verify the declared container image configuration.
[TOOL CALL 2]: get_deployment_history(deployment_name="nginx-export", namespace="default")
[TOOL RESULT]:
Deployment: nginx-export
Replicas Target: 1
Configured Containers & Images: ['nginx:nonexistent-tag-abc123']
[AGENT THOUGHT]: The image tag is confirmed as invalid. Let me run get_pod_logs just in case the container ran briefly.
[TOOL CALL 3]: get_pod_logs(pod_name="nginx-export-74d475bf7c-x89p2", namespace="default")
[TOOL RESULT]: Kubernetes API Error while fetching logs: BadRequest: container "nginx" in pod "nginx-export-74d475bf7c-x89p2" is waiting to start: image can't be pulled.
[AGENT THOUGHT]: I now have sufficient evidence to generate the complete incident report.
9. Generated Incident Investigation Report
After completing its tool iterations, the agent synthesizes the findings into a clear post-mortem report:
Kubernetes Incident Investigation Report
10. Advanced Configuration: Customizing Execution Behavior
You can alter how tools are ordered or prioritized by adjusting system prompts or modifying the configuration schema.
Dynamic Execution Ordering
By default, an LLM determines tool execution order based on the prompt context and tool docstrings. If an SRE team wants the agent to inspect application logs before cluster events, they can adjust the system prompt:
# System prompt instruction forcing diagnostic ordering
k8s_investigation_agent.system_instruction = (
"You are a strict SRE agent. Always execute diagnostic tools in this exact order: "
"1. get_pod_logs "
"2. get_pod_events "
"3. get_deployment_history "
"Do not jump to conclusions without executing all steps."
)
Summary and Key Takeaways
- The Production Gap: Passive log ingestion models fail in production because LLMs cannot interact directly with real-time cluster infrastructure without explicit tool bindings.
- Tool Calling Mechanics: Tools act as safe execution bridges, converting high-level LLM intentions into structured Python API commands (
kubernetes.client) and returning JSON payloads back to the model's context window. - Declarative Development via Google ADK: Using Agent CLI alongside the Google Agent Development Kit enables natural-language generation of complete Python tool definitions, schemas, and framework bindings.
- Multi-Tool Diagnostic Triangulation: Combining application logs (
get_pod_logs), cluster infrastructure events (get_pod_events), and resource change histories (get_deployment_history) ensures high diagnostic confidence () and eliminates false positives. - Handling API Faults: Tools should wrap cluster API execution calls in structured
try-exceptblocks, returning descriptive error messages to the model rather than crashing the execution runtime. - Custom Execution Protocols: The sequence and priority of tool calling can be adjusted via system instructions to align with standard SRE diagnostic workflows.
- End-to-End Automation: The agent evolves from a simple static text processor into an autonomous diagnostic engine capable of locating issues, gathering context, analyzing evidence, and recommending actionable remediations.