How to Configure Multiple Agents with Different LLM Providers in DAT
Configure multiple agents with different LLM providers by defining each model in the global llms array, then referencing specific model names in each agent's configuration section via the default-llm key.
The DAT framework (junjiem/dat) enables you to run multiple Askdata agents within a single project, each powered by distinct large language models. This architecture allows you to optimize costs and performance by assigning lightweight models to simple tasks and powerful models to complex reasoning workflows, all controlled through the dat_project.yaml configuration file.
Understanding the Architecture
The multi-agent, multi-LLM system in DAT follows a factory-based instantiation pattern. When you define agents in your project YAML, ProjectUtil.createAskdataAgent() handles the orchestration by loading the project configuration, building a ContentStore, and delegating to the appropriate AskdataAgentFactory based on the agent's provider field.
For agentic implementations, AgenticAskdataAgentFactory parses the agent-specific configuration options—specifically default-llm and optionally sql-generation-llm—and selects the corresponding ChatModelInstance from the globally defined LLM list. The resulting AskdataAgent uses the selected model for all conversations and tool invocations.
Step-by-Step Configuration Guide
1. Define LLM Providers in the Global Configuration
First, declare all available models in the top-level llms array of your dat_project.yaml. Each entry requires a unique name that agents will reference later.
llms:
- name: openai-gpt4
provider: openai
configuration:
api-key: ${OPENAI_API_KEY}
model: gpt-4
- name: anthropic-claude
provider: anthropic
configuration:
api-key: ${ANTHROPIC_API_KEY}
model: claude-2
- name: azure-gpt35
provider: azure-openai
configuration:
api-key: ${AZURE_API_KEY}
endpoint: ${AZURE_ENDPOINT}
model: gpt-35-turbo
2. Configure Individual Agents with Specific LLMs
Next, define your agents in the agents array. Use the configuration section to bind each agent to a specific LLM via the default-llm key. You can also specify a separate sql-generation-llm for text-to-SQL tasks.
agents:
# Agent using OpenAI GPT-4 for sales queries
- name: sales-assistant
description: "Answers sales-related queries with high accuracy"
provider: agentic
configuration:
default-llm: openai-gpt4
sql-generation-llm: openai-gpt4
max-messages: 150
data-preview: true
# Agent using Anthropic Claude for research tasks
- name: research-assistant
description: "Handles research-oriented questions"
provider: agentic
configuration:
default-llm: anthropic-claude
max-tools-invocations: 5
human-in-the-loop: false
# Agent using Azure OpenAI for compliance-sensitive operations
- name: compliance-auditor
description: "Audits compliance queries"
provider: agentic
configuration:
default-llm: azure-gpt35
sql-generation-llm: openai-gpt4
3. Optional: Restrict Semantic Models per Agent
You can further specialize agents by limiting which semantic models they access. This reduces retrieval latency and prevents context contamination between domains.
- name: medical-assistant
provider: agentic
configuration:
default-llm: openai-gpt4
semantic_models:
- medical_records
semantic_model_tags:
- health
Internal Implementation Details
The configuration parsing happens through several coordinated components in the DAT source code.
Project Loading: ProjectUtil.loadProject() in dat-sdk/src/main/java/ai/dat/boot/utils/ProjectUtil.java parses the YAML into a DatProject instance, extracting both the global llms list and the agents configurations.
Factory Resolution: When ProjectUtil.createAskdataAgent() is invoked, it retrieves the appropriate factory via AskdataAgentFactoryManager.getFactory(agentConfig.getProvider()) (defined in dat-core/src/main/java/ai/dat/core/factories/AskdataAgentFactoryManager.java).
Configuration Binding: The AgenticAskdataAgentFactory (in dat-agents/dat-agent-agentic/src/main/java/ai/dat/agent/agentic/AgenticAskdataAgentFactory.java) reads the ReadableConfig object and extracts:
default-llm: Maps to aChatModelInstancefrom the global LLM listsql-generation-llm: Optional separate model for SQL generation- Additional options like
max-messages,human-in-the-loop, etc.
Validation: FactoryUtil.validateFactoryOptions ensures that the LLM names referenced in agent configurations actually exist in the global llms array, preventing runtime errors.
Practical Java Example
To instantiate a specific agent programmatically:
import ai.dat.boot.utils.ProjectUtil;
import ai.dat.core.agent.AskdataAgent;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Map;
public class MultiAgentExample {
public static void main(String[] args) {
Path projectPath = Paths.get("/path/to/your/dat_project.yaml");
String agentName = "sales-assistant"; // Must match YAML name
Map<String, Object> variables = Collections.emptyMap();
// Creates the agent with its configured LLM (OpenAI GPT-4)
AskdataAgent agent = ProjectUtil.createAskdataAgent(
projectPath,
agentName,
variables
);
// Execute a query
String question = "What was the total revenue last quarter?";
var response = agent.ask(question, Collections.emptyList());
// Process the stream
response.events().forEach(event ->
System.out.println(event.content())
);
}
}
The same code works for any agent defined in your YAML; the specific LLM provider and model are automatically injected based on the agent's default-llm configuration.
Key Source Files Reference
| File | Role |
|---|---|
dat-sdk/src/main/java/ai/dat/core/data/project/AgentConfig.java |
POJO representing a single agent entry (name, provider, semantic_models, configuration). |
dat-agents/dat-agent-agentic/src/main/java/ai/dat/agent/agentic/AgenticAskdataAgentFactory.java |
Parses agent-specific configuration (including default-llm) and builds the concrete AskdataAgent. |
dat-sdk/src/main/java/ai/dat/boot/utils/ProjectUtil.java |
Loads the project YAML, creates the ContentStore, selects the proper factory, and returns a ready-to-use agent. |
dat-sdk/src/main/resources/templates/project_yaml_template.jinja |
Template used by the CLI to generate a starter dat_project.yaml; shows where to place LLM and agent sections. |
dat-core/src/main/java/ai/dat/core/factories/AskdataAgentFactoryManager.java |
Manages factory registration and resolution based on the provider string. |
dat-servers/dat-server-openapi/src/main/java/ai/dat/server/openapi/controller/InfoController.java |
Exposes /agents endpoint to verify that multiple agents are correctly registered. |
Summary
- Global LLM Registry: Define all available models in the top-level
llmsarray with unique names. - Agent-Specific Binding: Use the
default-llmkey in each agent'sconfigurationsection to select which model powers that agent. - Factory Pattern: The
agenticprovider usesAgenticAskdataAgentFactoryto parse configurations and instantiate agents with the correctChatModelInstance. - Validation: The framework validates that referenced LLM names exist in the global registry before runtime.
- Flexibility: You can mix providers (OpenAI, Anthropic, Azure) within one project and even assign different models for general chat versus SQL generation via
sql-generation-llm.
Frequently Asked Questions
Can I use the same LLM for multiple agents?
Yes. Multiple agents can reference the same LLM name in their default-llm configuration. The ChatModelInstance is shared according to the factory's implementation, but each agent maintains its own conversation state and tool configuration.
What happens if I specify an LLM name that doesn't exist in the global list?
The framework performs validation during agent creation. FactoryUtil.validateFactoryOptions checks that the default-llm and sql-generation-llm values match names defined in the top-level llms array. If a name is not found, agent instantiation fails with a configuration error before the agent can process any requests.
Can I assign different LLMs for chat and SQL generation within the same agent?
Yes. In addition to default-llm, you can specify sql-generation-llm in the agent's configuration section. This allows you to use a lightweight model for general conversation while employing a more capable model (such as GPT-4) specifically for generating complex SQL queries, optimizing both cost and performance.
How do I verify that all my agents are correctly registered with their LLMs?
You can query the /agents endpoint exposed by InfoController.java in the OpenAPI server module. This returns a list of all registered agents in the project, allowing you to confirm that each agent is present and that its configuration (including the linked LLM) has been loaded correctly without parsing errors.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →