{"componentChunkName":"component---src-templates-mdproject-jsx","path":"/projects/bkv_ai_agent_chat","result":{"data":{"allGithubFile":{"nodes":[{"base":"bkv_ai_agent_chat.md","relativeDirectory":"projects","childMarkdownRemark":{"id":"7b10c859-29ac-5144-b606-51d4e54fb56b","html":"<h1>AI Agent Chat - BKV Corporation</h1>\n<p>Software Engineer/Developer: Manuel Solalinde <a href=\"mailto:manolosolalinde@gmail.com\">(manolosolalinde@gmail.com)</a></p>\n<p>A full-stack <strong>conversational AI agent</strong> that lets reservoir, production, and operations staff ask natural-language questions about the company's wells and get grounded, tool-backed answers. The agent reasons over the corporate <strong>well database</strong>, searches internal documentation, browses the web, and runs Python in a sandbox — streaming each step (tool calls, intermediate results, and the final answer) back to the user in real time. It is built on <strong>Amazon Bedrock AgentCore</strong> and was forked and substantially extended from AWS Labs' fullstack AgentCore solution template (FAST).</p>\n<h2>Overview</h2>\n<p>A user opens the chat, asks a question in plain English (e.g. <em>\"find all wells spud in 2026\"</em> or <em>\"when was the last time the bumper spring was pulled on this well?\"</em>), and the agent decides which tools to call to answer it. The model writes and runs read-only SQL against the corporate well-data warehouse, looks up table/column documentation, retrieves internal datadocs, searches the web, or executes Python — then synthesizes a cited answer. Conversations are persisted with searchable history, auto-generated titles, and per-message feedback, so the tool behaves like an internal ChatGPT scoped to the company's own operational data.</p>\n<h2>Applications</h2>\n<ul>\n<li><strong>Natural-language data access</strong> — engineers query well headers, production, directional surveys, stimulation stages, and more without writing SQL themselves; the agent translates intent into validated read-only queries and explains its results.</li>\n<li><strong>Operational Q&#x26;A</strong> — answers grounded questions about specific wells, pads, and JV/GU units, citing the rows and documents it used.</li>\n<li><strong>Internal knowledge retrieval</strong> — hybrid (embedding + keyword) search over the company's internal documentation index, with full-document fetch.</li>\n<li><strong>Web research &#x26; code analysis</strong> — on-demand web search/fetch and a secure Python sandbox for ad-hoc computation, all inside the same conversation.</li>\n</ul>\n<h2>Architecture</h2>\n<p>A containerized, cloud-native stack on AWS, provisioned entirely as code with <strong>Pulumi (Python)</strong>:</p>\n<ul>\n<li><strong>Frontend</strong> — a <strong>React 19 + TypeScript</strong> single-page app (Vite, Tailwind CSS 4, shadcn/ui) served by <strong>Nginx</strong> on <strong>ECS Fargate</strong> behind an <strong>Application Load Balancer</strong>. A custom AgentCore streaming client parses Server-Sent Events to render tool calls, inputs, and results live as the agent works.</li>\n<li><strong>Backend API</strong> — a <strong>FastAPI</strong> service handling conversations, feedback, dynamic runtime config, and the agent proxy.</li>\n<li><strong>Agent Runtime</strong> — a containerized agent on <strong>Bedrock AgentCore Runtime</strong> (model: Claude Sonnet 4.5). The codebase ships <strong>four interchangeable agent patterns</strong> — Strands Agents (primary), LangGraph, and the Claude Agent SDK in both single- and multi-agent (Opus-orchestrates-Sonnet) configurations — selectable without touching the rest of the stack.</li>\n<li><strong>Tools via Gateway</strong> — Lambda-backed tools exposed over the <strong>AgentCore Gateway</strong> (MCP protocol): read-only SQL execution against the corporate well database, well-database table/column documentation lookup, internal datadocs hybrid search and retrieval, web search and page extraction, plus a Bedrock <strong>Code Interpreter</strong> sandbox.</li>\n<li><strong>Memory</strong> — <strong>AgentCore Memory</strong> provides session-scoped, persistent conversation history.</li>\n<li><strong>Data</strong> — <strong>DynamoDB</strong> stores conversations and feedback; <strong>SSM Parameter Store</strong> holds runtime ARNs and config.</li>\n</ul>\n<h2>Design decisions &#x26; trade-offs</h2>\n<ul>\n<li><strong>Four interchangeable agent patterns</strong> — Strands Agents, LangGraph, and the Claude Agent SDK in single- and multi-agent configurations are selectable without touching the rest of the stack, future-proofing the system against framework and model changes.</li>\n<li><strong>Read-only SQL execution</strong> — a deliberate safety decision: the agent can query the corporate well data but can never mutate it, preventing accidental data changes.</li>\n<li><strong>Separated user vs. machine-to-machine auth</strong> — keeping the two identity types distinct prevents user credentials from crossing the service boundary.</li>\n<li><strong>Lambda-backed tools over the AgentCore Gateway (MCP)</strong> — exposing tools through the Gateway decouples the agent runtime from tool implementations, so tools can evolve independently of the agent.</li>\n</ul>\n<h2>Hard problems solved</h2>\n<ul>\n<li><strong>Live streaming of agent reasoning</strong> — Server-Sent Events stream tool calls, inputs, intermediate results, and the final answer so they render live as the agent reasons, giving users visibility into multi-step reasoning instead of an opaque wait.</li>\n<li><strong>Hybrid internal-doc search</strong> — combined embedding and keyword search over internal documentation, with full-document fetch, to surface the most relevant grounding material.</li>\n<li><strong>Deploy-free local development</strong> — a local mode mocks authentication (no OIDC popup) and sources AWS credentials from the host profile, so the full chat flow runs end-to-end without deploying.</li>\n</ul>\n<h2>Authentication</h2>\n<p>The design keeps <strong>user identity</strong> and <strong>machine-to-machine identity</strong> fully separated:</p>\n<ul>\n<li><strong>User auth</strong> — users sign in through <strong>Microsoft Entra ID (OIDC)</strong>, and a validated token authorizes downstream services on the user's behalf.</li>\n<li><strong>Machine-to-machine</strong> — services authenticate to one another with <strong>Cognito</strong> OAuth2 client-credentials, managed by AgentCore Identity. Because the two identity types are separate, user credentials never cross the service boundary.</li>\n</ul>\n<h2>CI/CD &#x26; Local Development</h2>\n<ul>\n<li><strong>Two deployment paths</strong> — infrastructure, frontend, backend, and Gateway tools deploy via <strong>Pulumi</strong> (<code class=\"language-text\">pulumi up</code>), while agent code (system prompt, model, agent logic) deploys independently through the <strong>AgentCore CLI</strong> (<code class=\"language-text\">agentcore deploy</code>) which builds the agent container via CodeBuild.</li>\n<li><strong>Local environment</strong> — a <code class=\"language-text\">docker compose</code> stack runs the frontend, backend API, and agent together on a developer machine. A local-agent mode mocks authentication (no OIDC popup) and sources AWS credentials from the host profile, so the full chat flow can be exercised without deploying.</li>\n</ul>\n<blockquote>\n<p><em>Note: Screenshots and internal application URLs are omitted, as they display proprietary client data. Available on request, subject to client approval.</em></p>\n</blockquote>","frontmatter":{"title":"AI Agent Chat","image_url":"./images/covers/agent.png","description":"Full-stack conversational AI agent that answers oil & gas operational questions over corporate well data and internal documentation.","technologies":"Python, FastAPI, TypeScript, React, Vite, Tailwind CSS, shadcn/ui, Amazon Bedrock AgentCore (Runtime, Gateway, Memory, Code Interpreter), Strands Agents, LangGraph, Claude Agent SDK, AWS (ECS Fargate, ALB, Lambda, DynamoDB, SSM, Cognito), Pulumi, Docker, Nginx, Microsoft Entra ID, Server-Sent Events.","date":"2026-05-18T00:00:00.000Z"}},"user":"manolosolalinde","repository":"cv"}]},"site":{"siteMetadata":{"title":"Manuel Solalinde's Portfolio","description":"Manuel Solalinde's Portfolio and Featured Projects","author":"Manuel Solalinde"}}},"pageContext":{"uid":"bkv_ai_agent_chat.md","rootQuery":"\n    query mdProjectQuery($uid: String) {\n        allGithubFile(filter: {base: {eq: $uid}, relativeDirectory: {eq: \"projects\"}}) {\n            nodes {\n              base\n              relativeDirectory\n              childMarkdownRemark {\n                id\n                html\n                frontmatter {\n                  title\n                  image_url\n                  description\n                  technologies\n                  date\n                }\n              }\n              user\n              repository\n            }\n        }\n        site {\n            siteMetadata {\n                title\n                description\n                author\n            }\n        }\n    }\n"}},"staticQueryHashes":["3649515864"]}