Field Notes Blog cover AI-Assisted Development

Using Claude Code as an Agentic Development System: Advisor Agents, Memory, and Deploying to EKS

How I use Claude Code's agent system to build AI systems — with a mandatory Advisor that catches production bugs, persistent memory that compounds across sessions, and a full EKS deployment architecture.

AP
Ashutosh Upadhyay
Platform Engineer | AI/ML Infrastructure | AWS & Kubernetes

The Meta-Problem: Building AI With AI

I've built and deployed a production multi-agent AI system — 35 tools, 4 specialized agent roles, running on EKS with full Langfuse observability. But here's the meta question: how do you actually build and deploy these systems efficiently?

My answer: treat your development environment itself as an agentic system. I use Claude Code — not as a simple autocomplete, but as a multi-agent development platform with:

Key insight: The same patterns that make your AI system better (adversarial review, specialization, memory) also make your development process better when you apply them to how you use AI coding tools.

The Advisor Agent: Mandatory Architecture Review

The most impactful pattern in my setup is a mandatory Advisor agent — a senior reviewer that runs on the most capable model (Opus) and must be consulted before every significant decision.

# .claude/agents/advisor.md (simplified)
---
name: advisor
description: Senior architecture reviewer. Must be invoked before
  any significant decision, before finalizing plans, and after every
  code change.
model: opus
tools: Read, Grep, Bash  # Bash included for log/status reads; prompt instructs no file writes
---

You are a senior technical reviewer. You receive a structured summary
and give a concrete recommendation. You have read-only access to
verify claims against the actual codebase.

Rules:
- You are a REVIEWER, not an implementer. Never modify files.
- Identify the core risk or assumption being made.
- Flag architectural trade-offs that may not be obvious.
- Give a CONCRETE recommendation, not just pros/cons.
- Point out anything missing that would change your answer.

When the Advisor Must Be Invoked

This isn't optional or "nice to have." I've configured it as a hard rule:

1
Before starting work — before committing to any architecture or implementation approach
2
During work — when encountering recurring errors, unfamiliar APIs, or when changing approach
3
After every code change — before bumping versions or declaring something ready to deploy
4
Before declaring done — the final sanity check before shipping

Why this matters: The Advisor has caught production bugs in changes I considered "trivial" — wrong data types silently corrupting outputs, URL encoding issues that would expire after 7 days, iframe security headers that would block rendering in production. Every single one of these would have been a production incident.

The Development Workflow: Plan → Question → Implement → Review

Agentic Development Workflow with Advisor Phase 1: PLAN Ask clarifying questions Document approach in markdown Phase 2: QUESTION Second round of questions Refine plan based on answers ADVISOR REVIEW Phase 3: IMPLEMENT (Parallel Subagents) Agent: Task A Backend changes Agent: Task B Frontend changes Agent: Task C K8s manifests Agent: Task D Tests / Docs ADVISOR REVIEW Catches bugs in "trivial" changes Version Bump 14-file checklist Jenkins Build → EKS Memory Persists across sessions feedback + context
Figure 1: The full development workflow — plan, question, implement with parallel agents, mandatory advisor review, then deploy

Persistent Memory: Context That Compounds

One of the most underused features of Claude Code is its persistent memory system. I maintain a structured memory index that carries hard-won knowledge across sessions:

.claude/memory/ ├── MEMORY.md # Index — loaded every session ├── user_role.md # Who I am, what I work on ├── feedback_planning.md # "Always ask questions before implementing" ├── feedback_no_auto_commit.md # "Never git push without asking" ├── feedback_image_bump.md # "14 files to update on every version bump" ├── project_current.md # What version is live, what's pending ├── reference_pricing.md # Claude API pricing (verified, not guessed) └── feedback_conciseness.md # "No verbose output, lead with the answer"

Key memory types and their purpose:

Type What It Stores Why It Matters
Feedback Corrections + confirmed approaches The AI never repeats the same mistake twice
Project Current state, versions, blockers New sessions start with full context
Reference External resources, API versions, pricing Facts verified once, never hallucinated again
User Role, expertise level, preferences Explanations tailored to your level

Example: After I got burned 3 times forgetting to update one of 14 files during a version bump, that became a feedback memory. Now Claude Code always checks all 14 files on every version bump — because the memory carries that lesson forward permanently.

The Full EKS Deployment Architecture

Here's how the complete agentic AI system deploys to production on Amazon EKS:

Production EKS Deployment Architecture Users (Browser) NGINX Ingress + OAuth2 Proxy EKS Cluster (Namespace: ai-agent) SvelteKit UI deployment-ui.yaml | Service FastAPI Orchestrator deployment.yaml | Routes queries to agents Data Scout replicas: 2 Sonnet model Analyst replicas: 1 Sonnet model Synthesizer replicas: 1 Opus model Critic replicas: 1 Opus model CronJobs (Automated Ingestion) Daily: data refresh | Weekly: ontology | Ad-hoc: schema sync Monitoring Stack Langfuse traces | Prometheus metrics | ADOT (OpenTelemetry) AWS Services Bedrock Claude API S3 Data Lake DynamoDB Knowledge Graph Secrets Mgr ExternalSecret IAM (IRSA) SA → IAM Role ConfigMap: model selection, feature flags, cache TTLs NetworkPolicy: egress allow-list only
Figure 2: Full EKS production architecture — separate deployments per agent role, AWS services via IRSA, automated ingestion CronJobs

Key Kubernetes Patterns

1. Separate Deployment per Agent Role

Each agent role is its own Kubernetes Deployment with its own Service. This gives you:

2. ConfigMap-Driven Model Selection

# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: agent-config
data:
  SCOUT_MODEL: "us.anthropic.claude-sonnet-4-6"
  SYNTHESIZER_MODEL: "us.anthropic.claude-opus-4-8"
  CRITIC_MODEL: "us.anthropic.claude-opus-4-8"
  KNOWLEDGE_GRAPH_TABLE: "agent-kg"
  CACHE_TTL_HOURS: "24"
  TOKEN_BUDGET: "10000000"
  LANGFUSE_ENABLED: "true"

Model selection lives in a ConfigMap, not in code. When a new Claude model drops, you update the ConfigMap and restart pods — no code change, no build, no PR.

3. IRSA for Zero-Credential Pods

# iam/trust-policy.json (simplified)
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "Federated": "arn:aws:iam::ACCOUNT:oidc-provider/oidc.eks.REGION.amazonaws.com"
    },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
      "StringEquals": {
        "oidc.eks....:sub": "system:serviceaccount:ai-agent:agent-sa"
      }
    }
  }]
}

Pods assume IAM roles via IRSA (IAM Roles for Service Accounts). No AWS credentials stored anywhere — not in secrets, not in env vars, not in code. The pod's service account maps to an IAM role that grants access to S3, DynamoDB, Bedrock, and Secrets Manager.

4. Automated Data Freshness via CronJobs

# cronjob-auto-ingest.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: daily-data-refresh
spec:
  schedule: "0 6 * * *"  # 6 AM UTC daily
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      activeDeadlineSeconds: 21600  # 6-hour timeout
      template:
        spec:
          containers:
            - name: ingest
              image: agent:${VERSION}
              command: ["python", "-m", "agent.jobs.ingest", "--source", "all"]

Langfuse in the Production Stack

Langfuse sits alongside Prometheus and OpenTelemetry as part of the monitoring deployment:

Observability Stack — Three Pillars Prometheus + Grafana Infrastructure metrics Pod CPU / Memory Request latency (p95) Error rates CronJob success/fail Langfuse LLM-specific observability Per-role traces + spans Token cost per query Tool call success rates Quality scoring over time ADOT (OpenTelemetry) Distributed traces Cross-service spans AWS service call latency S3/DynamoDB timing Bedrock API tracking
Figure 3: Three-pillar observability — infra (Prometheus), LLM behavior (Langfuse), distributed traces (OpenTelemetry/ADOT)

The "Build the Builder" Feedback Loop

Here's the meta-pattern that makes all of this compound:

  1. Langfuse traces from the production agent reveal quality issues
  2. Those issues become development tasks in the next session
  3. The Advisor agent reviews the proposed fix
  4. Fix is implemented using parallel subagents
  5. Advisor reviews the implementation and catches edge cases
  6. Version bump (all manifest files) — Advisor verifies nothing was missed
  7. Deploy → Langfuse traces the improvement → loop

Every production observation becomes a development action. Every development session compounds knowledge into memory. The system gets better at building itself.

14
Files Per Version Bump
4
Agent Deployments
3
CronJobs (Daily/Weekly/Adhoc)

What I'd Do Differently Starting Today

1. Start with the Advisor pattern from day one

I added the mandatory Advisor after it caught its 4th production bug. If I'd had it from the start, those 4 bugs would never have shipped.

2. Set up Langfuse before writing the first agent

Retrofitting observability is painful. Instrument from the beginning. Even if the first version is one agent with one tool, trace it. The data compounds.

3. Use ConfigMaps for everything that might change

Model names, feature flags, cache TTLs, token budgets — if it might change without a code change, it belongs in a ConfigMap. I've updated models twice without a single line of code.

4. Write the memory system for your future self

Every hard-won lesson — every "oh, I missed that file again" or "that API changed" — goes into persistent memory immediately. Future sessions start where you left off, not from scratch.

The Full Stack — Summary

Layer Technology Purpose
Development Claude Code + Advisor Agent AI-assisted dev with mandatory review
Backend FastAPI + Strands SDK Agent orchestration + tool execution
Frontend SvelteKit Interactive research UI
Models AWS Bedrock (Claude) Tiered: Sonnet (fast) + Opus (reasoning)
Data S3 (Parquet) + DynamoDB Data lake + knowledge graph
Observability Langfuse + Prometheus + ADOT LLM traces + infra metrics + distributed traces
Platform EKS + IRSA + ExternalSecrets Zero-credential, auto-scaling Kubernetes
CI/CD Jenkins + Kustomize Build → push → deploy pipeline
Ingestion K8s CronJobs Automated data freshness

If you're building agentic AI systems, the investment in your development workflow is as important as the system itself. An Advisor that catches bugs before production, memory that compounds lessons, and Langfuse traces that reveal what's actually happening — these aren't luxuries. They're what separate a demo from a production system.

The tools exist. The patterns work. The main barrier is discipline: always invoke the Advisor, always trace with Langfuse, always persist lessons to memory. The compound effect is remarkable.

Coming soon: how I migrated this entire agentic platform from self-managed EKS deployments to AWS Bedrock AgentCore — reducing operational overhead while keeping the same multi-agent architecture. Stay tuned.

If you're building similar systems or have questions about deploying agents on EKS (or migrating off it), feel free to connect.

#ClaudeCode #AgenticAI #EKS #Kubernetes #Langfuse #DevWorkflow #PlatformEngineering #AWSBedrock #AIInProduction
Share

Comments & Discussion