All projects

Agent application engineering / 2026

Building beyond the demo

Lessons from building an agentic AI application with LangGraph, durable state, access control and observability, and preparing it for a first release.

LangGraphPythonSoftware ArchitectureAgent HarnessesFull Stack

The question behind the project

An AI agent produces a useful answer. Then a request times out, a user retries, or two operations touch the same data. What should the application do next?

That is the engineering question behind an independent product I’m developing: how do you turn an agent into a system whose behaviour you can understand, constrain and test? The product is still in development; this page focuses on the architecture and lessons from building it.

Giving the harness a clear role

An agent harness is the software around a language model that manages its use of tools, context and execution. I use Deep Agents, with LangChain’s model integrations and LangGraph’s runtime, as that foundation.

My work is in deciding how that foundation fits the application. I connect tools through explicit interfaces, package reusable instructions as read-only skills, and configure permissions and execution limits. The backend remains responsible for access checks and stored application state.

The lesson: choosing a harness is also choosing its boundaries. A capable agent still needs a clear definition of what it can access, change and report as complete.

Keeping the architecture understandable

I keep the code in one repository, with domain modules in the backend and separate user-facing and operational applications. This gives the project room to evolve without requiring every concern to become a separate service.

The main separation is between the agent’s execution, the application’s rules and its durable data. Typed contracts make the interfaces explicit. A streaming adapter translates runtime events into application events that the UI can handle.

Three responsibilities around the agent

  1. 01Harness · tools and context
  2. 02Application · rules and access
  3. 03Operations · visibility and limits
A conceptual view of responsibilities, not the product’s internal workflow or deployment topology.

One practical example is a late result arriving after a retry has taken over. I added ownership checks so the older operation cannot overwrite the newer one. That is an application-state problem as much as an AI problem.

Scaling starts with doing less work

I focused first on bounded work and measurable bottlenecks: limiting concurrent external requests, returning compact data for initial page loads, and batching telemetry writes. These changes address pressure on the application before adding more infrastructure.

Observability makes those decisions easier to assess. The implementation records request outcomes, model usage and timing, while a capacity-test harness checks concurrent streams alongside application health.

The distinction matters: these are scaling preparations and local engineering improvements. They do not yet establish capacity under production traffic.

Preparing for a first release

The project includes durable PostgreSQL state, database migrations, separate liveness and readiness checks, and automated tests for access boundaries, interrupted requests and stale operations. Container builds and CI make those checks repeatable.

My main learning is to treat release readiness as evidence to collect. A successful build answers a different question from a realistic load test or a session-isolation check against deployed infrastructure. The next validation step is exercising those behaviours together in staging with real dependencies.

Libraries and what they contribute

Building blockRole in the project
Deep Agents, LangChain & LangGraphAgent harness, model integrations and checkpointed execution state
FastAPI & PydanticPython API and validated data contracts
PostgreSQL, SQLAlchemy & AlembicDurable application data and schema migrations
Next.js, React & assistant-uiTypeScript application and conversational interface
Docker & GitHub ActionsRepeatable builds and automated checks

These libraries provide the foundations. My contribution is integrating them, defining the boundaries between them, and testing the behaviour of the resulting application. LangGraph’s persistence documentation explains the checkpointing mechanism used by the runtime.

The work is ongoing, with the emphasis on a maintainable first release. If you’re interested in agent integration, application architecture or the trade-offs along the way, let’s talk.

More questions. More things to build.

Back to projects