nOps rebuilt its Clara FinOps AI agent on Amazon Bedrock AgentCore, replacing a self-managed Amazon EKS stack running LangChain and LangGraph. The move cut time-to-production by 75% (from 10-12 months to 4 months), improved response quality, and reduced operational overhead while keeping analytics governed through Databricks Lakehouse Metric Views.
This is a migration story with hard numbers. It exposes the operational trade-offs between self-managed orchestration and managed agent infrastructure, and shows where the abstraction boundaries shift when you stop running your own Kubernetes pods.
What nOps Was Running Before
Clara is a FinOps agent that helps customers optimize cloud spend. The original stack:
- Amazon EKS for container orchestration
- LangChain for LLM integration
- LangGraph for multi-step workflow orchestration
- Custom state management for conversation context
- Manual prompt engineering and tool integration
The team owned the entire runtime. They managed Kubernetes deployments, scaling policies, observability pipelines, and the orchestration graph logic. Time-to-production for new agent capabilities: 10-12 months.
What Changed with AgentCore
AgentCore is AWS’s managed agent runtime. It abstracts:
- Orchestration logic: You define tools and guardrails, not execution graphs
- State persistence: Conversation context and session management are handled
- Prompt optimization: The service tunes prompts based on observed interactions
- Scaling: No pod autoscaling configs or cluster capacity planning
The new stack:
- Amazon Bedrock AgentCore for orchestration and runtime
- Databricks Lakehouse Metric Views for governed analytics queries
- AWS-managed observability through CloudWatch and X-Ray
- Declarative tool definitions instead of custom graph nodes
Time-to-production for new capabilities: 4 months.
Orchestration Responsibilities That Shifted
| Responsibility | LangGraph (Self-Managed) | AgentCore (Managed) |
|---|---|---|
| Execution graph | Explicit Python graph with nodes and edges | Implicit, inferred from tool definitions |
| State management | Custom persistence layer (DynamoDB or similar) | Managed session store |
| Prompt tuning | Manual iteration and A/B testing | Automatic optimization based on feedback |
| Tool routing | Conditional logic in graph nodes | Declarative tool schemas with auto-routing |
| Error recovery | Custom retry logic and fallback paths | Built-in retry policies and error boundaries |
| Observability | Custom instrumentation and log aggregation | Native CloudWatch and X-Ray integration |
The trade-off: You lose fine-grained control over execution order and branching logic. If your agent needs complex conditional workflows (e.g., “if tool A fails, try tool B, then C, but skip D”), LangGraph gives you explicit control. AgentCore infers routing from tool schemas and success signals.
Databricks Integration and Governance Boundaries
Clara queries financial data across multiple customer tenants. The integration with Databricks Lakehouse Metric Views maintains isolation:
- Metric Views are pre-defined, governed SQL queries exposed as semantic layers
- Each tenant’s data lives in separate Unity Catalog namespaces
- AgentCore calls Metric Views as tools, passing tenant context as parameters
- Databricks enforces row-level security and column masking at query time
The agent never writes raw SQL. It selects from a catalog of approved metrics (e.g., “monthly compute spend by service” or “unused reserved instances”). This keeps the LLM from generating arbitrary queries that could leak data across tenants.
Example tool definition (simplified):
tools:
- name: get_compute_spend
description: "Retrieve monthly compute spend grouped by service for a tenant"
parameters:
tenant_id:
type: string
required: true
start_date:
type: string
format: date
end_date:
type: string
format: date
endpoint:
type: databricks_metric_view
view_name: monthly_compute_spend
catalog: finops_metrics
AgentCore validates the tenant_id against the session context before executing the query. If the session belongs to tenant A, it cannot request data for tenant B.
Failure Modes That Changed
Before (LangGraph on EKS)
- Pod crashes: Kubernetes restarts the pod, but in-flight conversations are lost unless you persist state after every turn
- Graph execution errors: You see the exact node that failed and can replay from that point
- Prompt failures: You log the raw LLM response and manually adjust the prompt template
- Tool timeouts: You write custom timeout logic and fallback paths in the graph
After (AgentCore)
- Service-level failures: AgentCore retries automatically, but you don’t control the retry policy
- Opaque execution: You see tool calls and responses in CloudWatch, but not the internal routing decisions
- Prompt drift: The service optimizes prompts over time, which can change behavior without code changes
- Tool timeouts: Built-in timeout handling, but less visibility into why a tool was skipped
The debugging workflow shifts from “inspect the graph execution trace” to “review CloudWatch logs and X-Ray traces.” You lose the ability to step through the orchestration logic locally.
What Improved
Response quality: AgentCore’s automatic prompt tuning reduced hallucinations and off-topic responses. The service learns from user feedback signals (thumbs up/down, conversation abandonment) and adjusts prompts without manual intervention.
Operational overhead: No more Kubernetes cluster management, no custom scaling policies, no manual log aggregation. The team went from managing infrastructure to defining tools and guardrails.
Development velocity: New agent capabilities ship in weeks instead of months. Adding a new tool is a YAML definition and a Databricks Metric View, not a new graph node with custom error handling.
What You Give Up
Execution transparency: You can’t inspect the orchestration graph or replay a conversation step-by-step in a local debugger.
Custom branching logic: If your agent needs complex conditional workflows, you’re constrained by AgentCore’s routing model.
Prompt control: The service optimizes prompts automatically, which can drift behavior over time. You can override this, but it defeats the purpose of the managed service.
Cost visibility: AgentCore pricing is per-request, not per-pod-hour. If your agent makes many tool calls per conversation, costs can scale unpredictably.
When to Migrate
You should migrate if:
- You’re spending more time managing Kubernetes than building agent capabilities
- Your orchestration logic is simple (linear or lightly branching workflows)
- You want automatic prompt optimization and don’t need deterministic prompt behavior
- You’re okay with less execution transparency in exchange for faster iteration
You should stay on LangGraph if:
- You need fine-grained control over execution order and error recovery
- Your workflows have complex conditional logic that doesn’t map to declarative tool schemas
- You need to debug orchestration logic locally or replay conversations step-by-step
- You’re running agents at scale and want predictable per-request costs
Technical Verdict
AgentCore is a good fit for teams that want to ship agent capabilities fast and don’t need deep control over orchestration logic. The 75% reduction in time-to-production is real, but it comes from trading execution transparency for managed abstractions.
If your agent workflows are simple (call a few tools, synthesize a response) and you’re spending more time on infrastructure than features, the migration makes sense. If you need complex branching logic, local debugging, or deterministic prompt behavior, LangGraph gives you the control you need.
The Databricks integration shows how to maintain governance boundaries when agents query multi-tenant data. Pre-defined Metric Views and row-level security keep the LLM from generating arbitrary SQL, which is the right pattern for financial data.
The failure mode shift is the biggest operational change. You move from “inspect the graph trace” to “review CloudWatch logs,” which works for most teams but can slow down debugging when things go wrong.