Agentic AI
How I built a 35-tool AI agent that autonomously queries databases, builds knowledge graphs, and generates research reports — running on Kubernetes.
Most enterprise AI deployments today are glorified search boxes. You ask a question, it fetches from a vector database, and returns a summary. That's RAG. It's useful — but it's not agentic.
An agentic system doesn't just retrieve — it reasons, plans, executes, and iterates. It decides which tools to use, what order to call them in, whether the results are sufficient, and when to try a different approach.
Over the past year, I've built and deployed an agentic AI system with 35 specialized tools, a knowledge graph, automated data ingestion pipelines, and multi-agent collaboration — all running on EKS. Here's what I learned.
Key insight: The difference between a chatbot and an agent is not the model — it's the tool loop. An agent has a reasoning cycle: observe → think → act → observe again. The model is just the brain; tools are the hands.
The core architecture has three layers:
Here's what a single agentic "turn" looks like in practice:
# Simplified agent loop (using Strands Agents SDK)
from strands import Agent, tool
@tool
def query_data_lake(source: str, filters: dict) -> dict:
"""Query partitioned Parquet data from S3."""
path = f"s3://data-lake/{source}/"
df = read_parquet_with_filters(path, filters)
return {"rows": len(df), "summary": df.describe().to_dict()}
@tool
def write_knowledge_graph(nodes: list, edges: list) -> dict:
"""Persist discovered relationships to the knowledge graph."""
store.batch_write(nodes, edges, ttl_days=90)
return {"written": len(nodes) + len(edges)}
agent = Agent(
model="us.anthropic.claude-sonnet-4-6",
tools=[query_data_lake, write_knowledge_graph, ...], # 35 tools
system_prompt=RESEARCH_PROMPT
)
response = agent("What are the key pathways affected by BRCA1 mutations?")
# Agent autonomously: queries → analyzes → graphs → summarizes
The agent doesn't just call one tool. In a typical research query, it:
get_skills to load domain-specific rules for the topicThat's 6+ tool calls per user message — each one chosen by the model based on what it learned from the previous call.
The most powerful pattern I discovered is query-derived knowledge persistence. Every time the agent answers a research question, it extracts entities and relationships and writes them back to a graph database.
The key design decisions:
Raw tools aren't enough. The agent also needs to know when to use each tool and how to interpret results. I built a dynamic skills system that injects domain knowledge at query time:
SKILLS = {
"network_analysis": {
"knowledge": "Interaction databases contain experimentally validated edges...",
"key_concepts": ["confidence_score > 0.7 for high-confidence", ...],
"common_mistakes": ["Don't confuse gene-level vs protein-level IDs", ...],
"example_prompts": ["Find interactions for TP53 with score > 0.9"]
},
"dose_response": {
"knowledge": "IC50 curves use 4-parameter logistic fit...",
"key_concepts": ["Log-scale concentration", "Hill slope interpretation"],
"common_mistakes": ["Always verify identifier type matches the data schema"],
...
}
}
The agent calls get_skills(topic) as its first action, loading relevant domain rules before it
starts reasoning. This prevents the most common failure mode: the model "hallucinating" domain knowledge instead
of following validated rules.
My first version embedded documents into a vector DB. The problem? Scientific data is structured — tables, relationships, ontologies. Embeddings flatten structure. I ripped out the vector store and replaced it with direct Parquet queries + a graph database. Accuracy jumped immediately.
A 10,000-token system prompt made the agent confused about priorities. The dynamic skills system — loading only relevant knowledge per query — was the fix. Smaller, focused context = better tool selection.
A daily CronJob refreshes external data sources automatically. The agent always has fresh data without human intervention. This is the "boring infrastructure" that makes the AI actually useful.
For the first 3 months, I was flying blind — no traces, no per-tool latency, no cost breakdown. When the agent gave a bad answer, I had no way to reconstruct why. Adding Langfuse tracing was transformative: suddenly I could see exactly which tool returned bad data and which reasoning step went wrong. If you're building agentic systems, instrument with LLM-specific observability from day one.