pzza.works

Building Advanced Sub-Agents in Astreus

Berke (pzzaworks)Berke (pzzaworks)

December 1st, 2025

Multi-agent systems get interesting when specialized agents coordinate to solve a problem none of them could handle alone. In this guide I build production-ready agent teams with the Astreus framework, using real-world patterns for delegation, coordination and orchestration.

Environment Setup

Before building anything, configure your environment with the API keys and the database connection.

Bash
# .env file OPENAI_API_KEY=your-openai-key ANTHROPIC_API_KEY=your-anthropic-key DB_URL=sqlite://./astreus.db

The database URL is what turns on the memory and knowledge base features. SQLite is fine for development; for production deployments I recommend PostgreSQL.

Multi-Model Agent Architecture

Different models are good at different things. GPT-4o is strong at analytical reasoning, while Claude 3.5 Sonnet writes more natural, creative content. A good multi-agent system picks the model per task instead of using one model for everything.

The coordinator pattern is the one that works best for this. A coordinator agent looks at each request and delegates subtasks to specialist agents, and each specialist runs on the model that fits its role.

Creating the Strategic Planner Agent

The strategic planner handles high-level analytical reasoning and planning. Memory and a knowledge base give it the context it needs to make decisions.

TypeScript
const strategicPlanner = await Agent.create({ name: 'StrategicPlanner', model: 'gpt-4o', systemPrompt: 'You are a strategic planner. Analyze complex problems and develop comprehensive plans.', memory: true, knowledge: true });

Agent.create() instantiates an agent with its full configuration. Memory lets the agent learn from past interactions, and the knowledge base gives it access to curated information.

Building the Creative Writer Agent

Claude is the better choice for creative writing and narrative. Turning on vision lets the writer process images alongside text.

TypeScript
const creativeWriter = await Agent.create({ name: 'CreativeWriter', model: 'claude-3-5-sonnet-20241022', systemPrompt: 'You are a creative writer. Generate engaging, natural prose that connects with readers.', vision: true });

With vision, the writer can look at images, screenshots or diagrams and work that visual context into what it writes.

Implementing the Data Scientist Agent

The data scientist pairs analytical reasoning with tools for statistical analysis and data processing. Tools are registered with registerPlugin() after the agent is created.

TypeScript
const dataScientist = await Agent.create({ name: 'DataScientist', model: 'gpt-4o', systemPrompt: 'You are a data scientist. Perform statistical analysis and extract insights from data.' }); // Register tools via plugin system await dataScientist.registerPlugin({ name: 'analytics', version: '1.0.0', description: 'Data analysis tools', tools: [ { name: 'analyzeDataset', description: 'Perform statistical analysis on datasets', parameters: { dataset: { name: 'dataset', type: 'string', description: 'Dataset name or path', required: true }, metrics: { name: 'metrics', type: 'array', description: 'Metrics to calculate' } }, handler: async (params) => { // Implementation here return { success: true, data: { /* analysis results */ } }; } } ] });

Tools take an agent beyond text generation. The data scientist can call custom functions for specialized work like statistical calculations or database queries. Because tools go through the plugin system, the agent's configuration and its tool definitions stay cleanly separated.

Assembling the Executive Coordinator

The coordinator orchestrates the specialists to handle complex requests that span several areas. It takes its team through the subAgents parameter.

TypeScript
const executiveCoordinator = await Agent.create({ name: 'ExecutiveCoordinator', model: 'gpt-4o', systemPrompt: `You coordinate a team of specialist agents: - StrategicPlanner: for analytical reasoning and planning - CreativeWriter: for content creation and narrative - DataScientist: for data analysis and insights Analyze requests, delegate to appropriate specialists, and synthesize results.`, subAgents: [strategicPlanner, creativeWriter, dataScientist] });

Passing agents in the subAgents array is all it takes to give the coordinator the ability to delegate. The framework handles the routing and execution.

Delegation Strategies

The coordinator can delegate in different ways depending on the task. Sequential execution runs subtasks in order, and parallel delegation runs independent work at the same time.

TypeScript
const result = await executiveCoordinator.ask( 'Analyze market trends and create an executive summary', { useSubAgents: true, delegation: 'auto', coordination: 'sequential' } );

delegation: 'auto' lets the coordinator decide which specialists to bring in. Sequential coordination makes each subtask finish before the next starts, which matters whenever a later task depends on an earlier result.

Implementing Parallel Coordination

When subtasks are independent, parallel coordination cuts the total execution time significantly.

TypeScript
const parallelResult = await executiveCoordinator.ask( 'Research competitors A, B, and C', { useSubAgents: true, delegation: 'auto', coordination: 'parallel' } );

The coordinator dispatches several specialists at once, each researching a different competitor, and waits for all of them before it synthesizes the final response.

Memory Integration

Memory lets an agent learn from conversations and recall the context that matters. The extractionLevel parameter controls how aggressively the agent extracts facts.

TypeScript
const accountManager = await Agent.create({ name: 'AccountManager', model: 'gpt-4o', systemPrompt: 'You manage client relationships. Remember preferences, history, and needs.', memory: true });

Moderate extraction is the balance between coverage and precision: the agent remembers the key facts without filling storage with trivial details. The settings range from 'minimal' to 'aggressive'.

Knowledge Base Setup

A knowledge base gives an agent curated information. Memory comes from conversations; a knowledge base contains documents you add explicitly.

TypeScript
const supportAgent = await Agent.create({ name: 'SupportAgent', model: 'gpt-4o', systemPrompt: 'You help customers with product questions. Search the knowledge base for accurate information.', knowledge: true });

The agent searches the knowledge base semantically when it answers a question, which grounds its responses in authoritative sources instead of training data alone.

Error Handling and Retries

Production systems have to survive failures. Configure retry logic and a fallback model for when the primary model fails.

TypeScript
const resilientAgent = await Agent.create({ name: 'ResilientAgent', model: 'gpt-4o', systemPrompt: 'You handle customer requests reliably.', debug: true });

If the primary model still fails after its retries, the agent switches to the fallback automatically. Exponential backoff keeps the retries from hammering rate limits during a temporary outage.

Cost Optimization with Model Selection

Model prices vary a lot, and choosing models deliberately can cut costs by 50-70% without giving up quality where it matters.

TypeScript
// Premium model for complex analysis const analyst = await Agent.create({ name: 'Analyst', model: 'gpt-4o', systemPrompt: 'You analyze complex business problems.' }); // Cost-effective model for routine tasks const formatter = await Agent.create({ name: 'Formatter', model: 'gpt-4o-mini', systemPrompt: 'You format data into structured outputs.' });

GPT-4o-mini costs a fraction of GPT-4o per token. Use it for formatting, validation and basic transformations, where advanced reasoning is not needed.

The Triage Pattern

Put a fast, cheap model in front to filter requests before an expensive model ever sees them. For high-volume systems this cuts costs a lot.

TypeScript
const triageAgent = await Agent.create({ name: 'TriageAgent', model: 'gpt-4o-mini', systemPrompt: `Classify requests as: - simple: handle directly - complex: escalate to specialist - out-of-scope: not something we handle` }); const coordinator = await Agent.create({ name: 'Coordinator', model: 'gpt-4o', systemPrompt: 'Handle escalated complex requests.', subAgents: [triageAgent] });

The coordinator has the triage agent assess every request first. Simple requests never reach the expensive model, and that is where the savings come from.

Consensus Voting Pattern

For high-stakes decisions, have several agents analyze the question independently and decide based on how much they agree.

TypeScript
const riskAnalyst1 = await Agent.create({ name: 'RiskAnalyst1', model: 'gpt-4o', systemPrompt: 'You assess financial risk conservatively.' }); const riskAnalyst2 = await Agent.create({ name: 'RiskAnalyst2', model: 'claude-3-5-sonnet-20241022', systemPrompt: 'You assess financial risk conservatively.' }); const decisionMaker = await Agent.create({ name: 'DecisionMaker', model: 'gpt-4o', systemPrompt: 'Review risk assessments and make decisions. If analysts disagree, flag for human review.', subAgents: [riskAnalyst1, riskAnalyst2] });

Running each analyst on a different model lowers the chance that they share the same biases. When the analysts disagree, that is the signal the decision needs human judgment.

Monitoring Token Usage

For detailed token tracking, use the task-based API, which returns usage statistics.

TypeScript
const task = await executiveCoordinator.createTask({ prompt: 'Generate quarterly market analysis', useSubAgents: true }); const result = await executiveCoordinator.executeTask(task.id); console.log(`Response: ${result.response}`); console.log(`Total tokens: ${result.usage?.totalTokens}`);

The task-based API returns detailed execution information, token usage included. That data is what you use to tune prompts and understand where the money goes.

Crafting Effective System Prompts

A clear system prompt defines an agent's behavior precisely. Spell out the role, the responsibilities and the boundaries.

TypeScript
const contractAnalyzer = await Agent.create({ name: 'ContractAnalyzer', model: 'gpt-4o', systemPrompt: `You analyze legal contracts for business clients. Responsibilities: - Identify key terms, obligations, and deadlines - Flag unusual or risky clauses - Summarize in plain English Boundaries: - Never provide legal advice, only analysis - Cite specific sections when flagging issues - Acknowledge limitations of automated review` });

Explicit boundaries keep an agent from stepping outside its expertise. The contract analyzer will not try to give legal advice, so its output stays in scope.

Real-World Example: Research Pipeline

Here is a complete multi-agent system that generates research reports, with parallel processing and a quality check at the end.

TypeScript
import { Agent } from '@astreus-ai/astreus'; // Data collection agent const dataCollector = await Agent.create({ name: 'DataCollector', model: 'gpt-4o', systemPrompt: 'You gather and analyze market data.' }); // Competitive intelligence agent const competitiveIntel = await Agent.create({ name: 'CompetitiveIntel', model: 'gpt-4o', systemPrompt: 'You analyze competitors and market positioning.' }); // Report writer using Claude const reportWriter = await Agent.create({ name: 'ReportWriter', model: 'claude-3-5-sonnet-20241022', systemPrompt: 'You write executive reports. Create clear, compelling narratives.' }); // Quality assurance with cost-effective model const qualityChecker = await Agent.create({ name: 'QualityChecker', model: 'gpt-4o-mini', systemPrompt: 'You check reports for errors and clarity issues.' }); // Research coordinator const researchCoordinator = await Agent.create({ name: 'ResearchCoordinator', model: 'gpt-4o', systemPrompt: `You coordinate research projects. Workflow: 1. DataCollector and CompetitiveIntel work in parallel 2. ReportWriter synthesizes their findings 3. QualityChecker reviews final output 4. Return polished report`, subAgents: [dataCollector, competitiveIntel, reportWriter, qualityChecker] }); // Execute the pipeline const report = await researchCoordinator.ask( 'Generate market research for electric vehicles in North America', { useSubAgents: true, coordination: 'sequential' } ); console.log(report);

The system uses GPT-4o's analytical strength for the data and competitive analysis, Claude's writing for the report, and a cheap model for QA. The coordinator runs the whole workflow on its own.

Running the Examples

You can run the official examples by cloning the repository, or install the package into your own project.

Bash
# Clone and run examples git clone https://github.com/astreus-ai/astreus cd sub-agents-advanced npm install npm run dev # Or install package for your own project npm install @astreus-ai/astreus

The repository has complete working examples of every pattern in this guide.

Testing Multi-Agent Systems

Test each agent on its own first, then test the coordination logic with integration tests.

TypeScript
// Test individual agent const writerResult = await creativeWriter.ask( 'Write a product description for wireless headphones' ); assert(writerResult.length > 100); assert(writerResult.includes('wireless')); // Test coordination const coordinatedResult = await executiveCoordinator.ask( 'Create a marketing campaign for wireless headphones', { useSubAgents: true } ); assert(coordinatedResult.length > 0); assert(coordinatedResult.includes('target audience'));

The integration tests check that the agents actually collaborate and that the coordinator routes each task to the right specialist.

Production Instrumentation

In production, add thorough logging and monitoring.

TypeScript
const productionAgent = await Agent.create({ name: 'ProductionAgent', model: 'gpt-4o', systemPrompt: 'You handle customer requests.', debug: true });

Good instrumentation is how you debug issues, understand usage patterns and tune performance based on how the system behaves in the real world.

Key Takeaways

An advanced sub-agent system uses several models deliberately, tied together by coordination patterns. Agent.create() instantiates each agent with its full configuration, including memory, knowledge bases and tools.

Delegation comes from the useSubAgents option plus a coordination strategy, sequential or parallel. Track token usage and cost so you can choose models with real numbers behind the choice.

Give memory to agents that need conversation context, and knowledge bases to agents that need grounding in authoritative sources. Add retries and fallback models so the system holds up in production.

Start with clear system prompts that define each agent's role and boundaries. Test agents individually and as a coordinated system, and use instrumentation to learn from real usage and keep improving the architecture.

This experiment is written for Astreus v0.5.37. Please ensure you are using a compatible version.

Keep reading

  • Building Basic Sub-Agents in Astreus

    Learn how to create and coordinate multiple AI agents using Astreus. Build specialized agents that work together under a coordinator for complex task delegation.

  • Building Graph Sub-Agents in Astreus

    Learn how to combine Graph workflows with Sub-Agent coordination for hierarchical task distribution in Astreus. Create specialized agents and orchestrate them through graphs.

  • Building Agents with Memory in Astreus

    Learn how to build AI agents with persistent memory using Astreus. Store conversation history and retrieve context across sessions.