Most enterprise AI applications don't fail because the language model is inaccurate.
They fail because the architecture around the model doesn't scale.
A single prompt quickly becomes dozens of prompts. One model becomes several. Tool invocations, retries, branching logic, structured outputs, auditability, and observability gradually turn a simple chatbot into a distributed workflow.
Eventually your codebase starts looking like this:
- prompt templates scattered across services
- JSON parsing everywhere
- retry logic duplicated
- model-specific code leaking into business services
- orchestration implemented as nested
ifstatements
At that point, you're no longer building an AI feature.
You're building an orchestration engine.
This is where agentic workflows become valuable.
Rather than treating an LLM as a smarter REST endpoint, you model AI execution as a deterministic workflow composed of specialized agents, explicit dependencies, branching decisions, and typed outputs.
In this article we'll build a production-ready market intelligence pipeline using Agentican and Quarkus while discussing the architectural decisions behind each step—not just the framework features.
The Architecture
Our workflow performs four independent responsibilities:
- Discover the leading vendors within a market.
- Research every vendor independently.
- Decide whether the findings require immediate attention.
- Produce an executive-ready briefing.
Instead of asking one enormous prompt to perform all four tasks, we deliberately separate responsibilities across specialized agents.
That separation provides several advantages:
- prompts become smaller and easier to maintain
- every step can be tested independently
- failures are isolated
- parallel execution becomes possible
- different models can be assigned to different tasks
- workflows remain understandable months later
This is the same principle architects already apply to microservices and event-driven systems: separate concerns before optimizing implementation.
Prerequisites
You'll need:
- Java 25
- Quarkus
- Maven (or Gradle)
- An LLM provider API key
Step 1: Add the Runtime
Start with a standard Quarkus application and include the Agentican runtime.
<dependency>
<groupId>ai.agentican</groupId>
<artifactId>agentican-quarkus-runtime</artifactId>
<version>0.1.0-alpha.3</version>
</dependency>Nothing unusual here.
The interesting part begins when we stop writing prompts inside Java code.
Step 2: Design the Workflow Instead of Coding It
Many AI frameworks encourage developers to embed prompts directly inside Java methods.
That works for prototypes.
It becomes painful in production.
Prompt engineering, workflow evolution, and operational tuning happen continuously after deployment. Treating prompts as configuration rather than source code lets engineering teams iterate without constantly modifying business logic.
Agentican separates three concerns:
- Agents define expertise.
- Skills define available capabilities.
- Workflows define orchestration.
This makes the execution graph explicit instead of hidden inside imperative Java code.
Create an agentican-catalog.yaml file.
The first section defines the specialists participating in the workflow.
(keep existing YAML exactly as provided for agents and skills)
Now define the workflow itself.
(keep existing workflow YAML essentially unchanged)
Why This Design Matters
Experienced architects will notice several architectural patterns hiding inside what appears to be simple YAML.
Agent specialization
Instead of one "super agent," we use a researcher and a writer.
Large prompts that ask one model to discover, analyze, classify, and summarize information often accumulate hallucinations because every responsibility competes for context.
Specialized agents generally produce more predictable outputs.
Parallel fan-out
The loop step isn't merely syntactic sugar.
type: loopEach vendor investigation becomes an independent execution path.
Since these tasks don't depend on one another, Agentican executes them concurrently using Java virtual threads.
Architecturally, this converts an O(n) sequential workflow into a parallel fan-out pattern that dramatically reduces latency for research-heavy pipelines.
Explicit dependencies
Notice that later steps consume earlier outputs.
{{step.deep-dive.output}}Rather than manually passing intermediate state between services, dependencies become part of the workflow definition itself.
This makes execution easier to reason about and far easier to visualize.
Deterministic branching
Rather than asking the model to "decide what to do next" inside one massive prompt, branching becomes explicit.
type: branchThe classifier produces a simple routing decision:
urgentstandard
The orchestration engine - not the model - controls execution flow.
That distinction significantly improves reproducibility.
Typed workflow parameters
Template interpolation keeps prompts declarative.
{{param.topic}}{{item}}{{step.identify.output}}The workflow owns the state while individual agents remain focused on reasoning.
Step 3: Configure the Models
Agentican separates orchestration from model providers.
The simplest configuration points every agent to a single LLM.
agentican.llm[0].api-key=${ANTHROPIC_API_KEY}By default this uses Claude Sonnet 4.5.
Switching providers requires configuration rather than code changes.
agentican.llm[0].provider=openai
agentican.llm[0].api-key=${OPENAI_API_KEY}
agentican.llm[0].model=gpt-4o-miniMore interestingly, production systems rarely rely on a single model.
Research agents may benefit from larger reasoning models, while summarization agents often perform perfectly well on smaller, faster, and significantly cheaper models.
Agentican allows multiple model configurations.
(keep existing multiple-model configuration unchanged)
This enables workload-specific optimization without changing workflow definitions.
Step 4: Expose the Workflow Through a Typed API
One common criticism of LLM applications is their lack of type safety.
Everything eventually becomes strings.
Instead, define explicit input and output contracts.
public record ResearchParams(String topic, int vendorCount) {}
public record VendorBrief(String topic, List<Vendor> vendors) {
public record Vendor(String name,
String positioning,
List<String> strengths) {}
}The workflow can now be injected like any other Quarkus component.
(keep existing Java endpoint unchanged)
Calling the endpoint is straightforward.
curl -X POST http://localhost:8080/market-brief/data%20observability%20platformsUnder the hood several important things happen.
ResearchParams.vendorCountmaps automatically tovendor_count.start()returns a typedWorkflowRun.await()converts the final workflow output directly into aVendorBrief.
The result feels much closer to invoking a domain service than interacting with an LLM.
That's exactly the abstraction enterprise developers usually want.
Step 5: Connect External Systems
Real-world agentic systems spend surprisingly little time talking to language models.
Most of their work involves interacting with external systems.
Whether that's GitHub, Jira, Salesforce, Slack, Google Workspace, or internal APIs, AI becomes valuable only when it can operate on live business data.
Agentican supports two complementary approaches.
MCP
Model Context Protocol servers expose external capabilities as discoverable tools.
(keep existing MCP configuration unchanged)
Composio
For SaaS integrations, Composio provides hundreds of ready-made connectors.
(keep existing Composio configuration unchanged)
Once configured, tools become available directly inside workflow steps.
(keep existing YAML tool example unchanged)
This keeps orchestration declarative while avoiding provider-specific integration code throughout the application.
From Prompt Engineering to Systems Engineering
Perhaps the most significant shift in enterprise AI isn't the emergence of better language models.
It's the recognition that AI applications increasingly resemble distributed systems.
They require orchestration, typed interfaces, concurrency, observability, deterministic execution paths, and well-defined contracts between independent components.
Prompt quality still matters.
But architecture matters more.
Agentican brings those architectural concerns into the Java ecosystem using patterns that experienced Quarkus developers already understand: dependency injection, configuration over code, typed APIs, and explicit workflow definitions.
Rather than embedding AI throughout the application, it treats AI as another orchestrated component inside a well-designed software system.
That distinction becomes increasingly important as AI moves from experimental features to production infrastructure.


