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 if statements


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:

  1. Discover the leading vendors within a market.
  2. Research every vendor independently.
  3. Decide whether the findings require immediate attention.
  4. 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.

XML
<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.

YAM
type: loop


Each 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.

YAML
{{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.

YAML
type: branch


The classifier produces a simple routing decision:

  • urgent
  • standard

The orchestration engine - not the model - controls execution flow.

That distinction significantly improves reproducibility.


Typed workflow parameters


Template interpolation keeps prompts declarative.

YAML
{{param.topic}}
YAML
{{item}}
YAML
{{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.

PROPERTIES
agentican.llm[0].api-key=${ANTHROPIC_API_KEY}

By default this uses Claude Sonnet 4.5.

Switching providers requires configuration rather than code changes.


PROPERTIES
agentican.llm[0].provider=openai
agentican.llm[0].api-key=${OPENAI_API_KEY}
agentican.llm[0].model=gpt-4o-mini

More 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.

JAVA
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.


Shell
curl -X POST http://localhost:8080/market-brief/data%20observability%20platforms


Under the hood several important things happen.

  • ResearchParams.vendorCount maps automatically to vendor_count.
  • start() returns a typed WorkflowRun.
  • await() converts the final workflow output directly into a VendorBrief.

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.