What Native Agentic Architecture Actually Looks Like

I recently argued that bolting an agent framework like LangChain onto a workflow engine creates architectural debt that compounds as you scale. Now I want to show you what I mean on a more technical level. Architecture arguments alone are too easy to nod along to, and just as easy to wave away.

In a customer context, my colleague Niall Deehan built the same KYC onboarding use case twice:

  • Once using Camunda 7 orchestrating a LangChain agent that runs in Python and calls its tools over REST.
  • And once as a native agentic orchestration on Camunda 8, where the agent and its tools live inside the process model itself.

Here are the two architectures and process models for the same problem side by side. I’ll call the first one the bolt-on and the second the native build for the rest of this post.

Camunda 7 is shown on the left with the bolt-on example, and Camunda 8 on the right with the native build example.

The two architectures side by side: on the left, the bolt-on, using Python-based agents; on the right, the native architecture, using integrated agentic orchestration.

KYC is a good example because it exercises everything that stresses an agent architecture:

  • It runs long, because documents arrive late and third parties respond slowly.
  • It involves several humans with distinct roles, a clerk who gathers information and an approver who signs off.
  • It has to stay consistent, because it is a critical operational process.
  • It also branches constantly: what an agent should do next depends heavily on what a tool just returned, and sometimes a result turns out to be wrong after the fact—a location check run against a mistyped address is worthless once the correction comes in, and the agent needs to know to discard it, not just add to it. And a regulator can come back months later and ask exactly what happened.

Let me start by explaining how the agent in the bolt-on architecture actually does its work, because that sets up the problem most people underestimate.

How the bolt-on agent does its work

In the bolt-on build, the agent is implemented as a typical agent-framework loop: pick a tool, run it, read the result, repeat until done. The model looks at the goal and the tools available to it, picks one, the tool runs, the model reads the result, and it goes around again until it decides it has enough to answer.

Stripped down, the code is essentially this:

# Build the ReAct loop: decide -> call tool -> read result -> repeat
agent = create_react_agent(llm, tools)   # tools: check_sanctions, verify_address, calculate_risk, ...

# One synchronous call, on one thread, inside one transaction
result = agent.invoke(application)

# Conceptually, inside invoke():
#   while not done:
#       tool   = llm.decide_next_tool(context)   # the model chooses
#       output = tool.run(...)                    # the side effect happens here, in-thread
#       context = context + output                # the loop's state lives in memory
#   return structured_decision(context)

# Error handling sits OUTSIDE the loop:
if any_tool_failed(result):
    raise RuntimeError(...)   # the worker fails, Camunda retries,
                              # and the whole invoke() runs again from the top

The important part is what that structure implies. The entire loop, every tool call included, runs in one synchronous invocation, on one thread, inside one transaction. The context the agent has built up lives in memory for the duration of that call and nowhere else.

The entire loops is the unit of retry. If any tool fails, the call returns and needs to be retried via invoke() as a whole.

The bolt-on agent’s reasoning loop: one call, one thread, one transaction. If any step fails, the whole loop is what gets retried.

Meet the consistency problems of the bolt-on architecture

Now walk a failure through that structure. The agent has already validated the address and created a customer record. On its next step, it calls the sanctions screening service, and that call times out.

The code raises an exception, the worker reports a failure, and the Camunda workflow above does the sensible thing: it creates a retryable incident and tries again. But “retry” here means reinvoking the whole agent from the top. The entire reasoning loop starts over, and every tool the agent decided to call before, it calls again. You pay for that twice: in latency, redoing work that already succeeded, and in tokens, re-reasoning your way back to where you already were.

The deeper problem is consistency. Some of those earlier tools had side effects. The customer record might have been created. Maybe an email went out, or a screening request was already logged with a third party.

Raising a Python exception does not roll any of that back. The remote systems did their work and have no idea the loop later fell over. So you are now sitting in an inconsistent state, and nothing owns putting it right. This is not even eventual consistency, which would imply that something is working toward convergence. You have nothing caring about consistency.

This is a well-known orchestration problem: coordinating work across systems that do not share a transaction. It is the class of problem the saga pattern exists to solve, and something I have written and talked about for years in the context of microservices. It’s back with full force now that agents are in the picture.

Agents make it especially easy to trip over: a reasoning loop tends to call a lot of tools, and consistency isn’t yet a built-in concern for most of them.

A KYC agent built of Camunda 7 + LangChain demonstrating where consistency breaks

The bolt-on build, step by step. Two side effects have already been committed by the time the sanctions check times out, and the retry reruns the entire loop from the top.

The same situation with native agentic orchestration

In the native build, workflow, agent, and tool calls live in a single model, deployed on Camunda 8. The LLM decides which tool to call and in what order. The engine executes the tool, stores the state, and handles what happens when a call fails. They are not the same thread and not the same transaction. Each tool call is a job the engine hands out and waits on.

So when the sanctions call times out, the engine does not throw the reasoning away. It pauses the process instance at that step and gives you a set of strategies to choose from, each modeled explicitly rather than buried in worker code:

  • Retry. Attempt the call again, immediately or on a schedule, for as long as makes sense for a transient failure like a timeout.
  • Wait for a human. Turn the failure into an incident an operator can pick up and resolve, then let the instance continue where it left off.
  • Compensate and reroute. Undo the work already done, in reverse order, and send the instance down a different path. This is the saga pattern, expressed directly in the model.
  • Escalate. Hand the case to a human with full context when it is beyond what the agent should decide on its own.

The part I find most interesting is what happens to the agent’s context. Instead of a failure blowing up the loop, the failure can come back as a result the agent reasons about on its next cycle. “The sanctions service is unavailable” is information. A capable agent can decide to run a different check, flag the case, or wait, rather than dying and being reborn with no memory of what it just learned. You keep the context, you do not re-burn the tokens, and you get a considered response instead of a blunt restart.

None of this is exotic. It is the documented shape of agentic orchestration on Camunda 8: the LLM chooses from a governed set of tools, and the engine handles execution, state, retries, and incidents.

The same situation shown in the last image, only this time the KYC agent is Camunda 8, native.

The same failure in the native build. The engine pauses at the point of failure instead of unwinding the whole loop, and offers a choice of explicit recovery strategies.

More structural problems with the bolt-on architecture

Consistency is the sharpest problem, but it is not alone. Building the same use case both ways surfaced other places where the bolt-on architecture leaks.

  • Tool calls are invisible. In the bolt-on version, what the agent invoked is a Python thread that returned a value. There is no durable record of which tool ran, with what inputs, under whose authority. For KYC that is a serious problem. A regulator may ask what you screened this applicant against, and when. In the native version the tools are activities in the process model, so what was called and when becomes part of the execution history automatically and is easy to see and inspect.
  • Long-running state has to be rebuilt by hand. The agent loop lives in a thread, so the moment something needs to wait, for a document upload, a human review, or a third-party callback, you either return to the workflow engine (and lose the agent’s context) or you build your own state persistence yourself. In the native build, waiting is normal. The agent pauses at a review gate or a callback and resumes later with full context.

It also means a tool can itself be a long-running subprocess, which is not expressible as a tool in a Python agent, because a tool has to return within the thread. In the native model, that is a call activity (aka, long running sub process) used as a tool.

  • Transaction boundaries are implicit and wrong. This is the consistency problem above, stated as a design property. Synchronous, in-thread tool execution gives you one transaction for the whole loop and no clean recovery when it half-completes. The native model makes the boundaries explicit, so partial failure triggers compensation instead of leaving debris behind.
  • You cannot tell a running agent anything new. A Python agent only learns by asking, by calling a tool to fetch what it wants. If the world changes while it is running—say a location check comes back, and the address behind it later turns out to be mistyped—there is no way to feed that correction into the loop, and no way for the agent to know the earlier result is now invalid. That’s a sharper problem in the bolt-on architecture than it sounds: the agent already breaks context between calls on every restart, so a correction like this easily gets lost in the shuffle even when someone goes looking for it. The native version has event subprocesses that inject new context into a running instance.

To be precise, this is not a remote control for steering the agent’s decisions. It is a way to hook new information into a loop the agent did not think to ask about. The agent still decides what to do with it. But being able to enrich its context mid-run, without it asking, changes what is possible.

Seeing the audit trail

Gray is all theory. The moment people get it is typically in a live demo, specifically when we show Camunda’s operations tooling. In the bolt-on case, the screen shows three opaque strings returned from the Python agent. In the native case, it’s a complete, clickable trail. That difference is more persuasive than any architecture diagram.

Camunda 7 Cockpit after the bolt-on agent task finishes. The process view confirms the step ran, but the data about agents and tools is very limited.

Camunda 7 Cockpit after the bolt-on agent task finishes. The process view confirms the step ran, but the data about agents and tools is very limited

The real information is sitting in the Python agent’s application log, as unstructured console output mixed with framework internals.

The real information is sitting in the Python agent's application log, as unstructured console output mixed with framework internals.

In Camunda 8 Operate, you can see every tool the agent called, with its inputs, outputs, and timing.

In Camunda 8 Operate, you can see every tool the agent called, with its inputs, outputs, and timing.

And because the LLM call is itself a step in the process, what was sent to the model and what came back is captured too, correlated to this exact case, alongside every tool call. For a regulated business process, that’s not a nice-to-have. It’s the difference between being allowed to run an agent in production and not.

To make that concrete rather than just claim it, I quickly vibe-coded a small interface on top of Camunda’s API that lays out one case as a timeline: reasoning and tool calls, in order, in a shape closer to what a regulator would actually want to read. It’s not a polished product, just proof that the data is there and that shaping it for a specific audience is just an afternoon’s work.

The audit data can be accessed via Camunda's API, so you can also build custom views for specific target audiences, like a regulator.

The audit data can be accessed via Camunda’s API, so you can also build custom views for specific target audiences, like a regulator.

Missing the reengineering opportunity

And if those technical issues were not enough, there is a larger point hiding behind the plumbing.

KYC today takes weeks. Not because the checks themselves are slow, since a sanctions screen returns in seconds, but because the process was built around human queues and document handoffs. The process is basically waiting in inboxes most of the time.

Bolt an agent onto that process and you make single review steps faster but leave the overall process shape intact. That is only a modest optimization, but it is what you are limited to, especially because process and agent logic live in different worlds.

But you could do much better. If you have one integrated model that contains the process flow, the LLM invocations, the tools, and all the human interactions, you can change the shape of the process itself.

Picture a straightforward applicant, an existing customer opening a second account. In the old process their file joins a queue. A clerk eventually opens it, requests a proof of address, and moves on to the next case. Days later the document arrives and waits for the same clerk to come back to it. The sanctions screen and the address check run one after another, because each one is a task in someone’s list. None of these steps is slow on its own. The application is simply idle between people.

In a redesigned flow, the moment the application arrives the process starts the address check, the account lookup, and the sanctions screen at the same time, because nothing forces them into a line. For this applicant they all come back clean, the agent assembles the case, and the whole thing finishes in minutes without anyone touching it. Nobody had to be free, and nothing sat in a queue.

Now change one detail. The sanctions screen returns a near-match that needs a judgment call. This is the only case that stops, and it stops only for the part that genuinely needs a person. The clerk opens a prepared file that shows what was checked, what matched, and what the agent has already ruled out, makes the one decision that required them, and the process continues on its own. And if the applicant uploads the missing document an hour later, the running instance picks it up and carries on, instead of waiting for the next time someone opens the file.

What used to take weeks now finishes in hours, and in minutes for the clean cases. The checks never got faster. What disappeared is the waiting between them, and redesigning the process to remove that waiting is what the integrated model makes possible.

A different problem shape

None of this means the bolt-on approach is bad, or that agent frameworks are bad in general. They’re good at what they were built for. The issue is the problem shape. When your agentic process is long-running, involves several humans with distinct roles, has to correlate external events, must hold a defined consistency because it is a critical operational process, and has to produce an audit trail a regulator can interrogate, you are outside the envelope both were designed for.

The native architecture with Camunda 8 isn’t more complex. It just puts the complexity where the problem actually has it. The failure handling, the waiting, the consistency, and the audit trail are part of the model, instead of scattered through worker code you will be maintaining by hand. This enables the use of agentic technology for critical processes like this one.

The native build of the KYC example is on GitHub, so you can read the real thing rather than take my word for it. I am deliberately not publishing the bolt-on version as a companion repo. It works (and I am happy to give you the code upon request), but I would rather not have anyone mistake it for a reference architecture, which is the whole point of this post.

I can just motivate you to play with true agentic orchestration yourself:

Similar Posts

Leave a Reply