# Understanding Fabric Agent Types: Orchestrator, Composable, and Custom Agents

> A guide to the three kinds of AI agent in Fabric, when to use each, how they work, and practice for building systems of several agents.

Canonical: https://fabric.pro/blog/understanding-fabric-agent-types
Published: 2026-01-03 by Preetham Reddy

---

Fabric Portal provides three distinct types of AI agents, each designed for different use cases and architectural patterns. This guide will help you understand when to use each type and how to build effective multi-agent systems.

## Overview of Agent Types

Fabric supports three categories of agents:

1. **System Agents** - Pre-built agents for common patterns (Orchestrator, Composable)
2. **Custom Agents** - Build your own specialized agents with various frameworks

### Quick Comparison

| Agent Type | Best For | Complexity | Customization |
|------------|----------|------------|---------------|
| **Orchestrator Agent** | Multi-step tasks requiring coordination | Low | Limited |
| **Composable Agent** | Hierarchical agent systems | Medium | Medium |
| **Custom Agent** | Specialized domain tasks | High | Full |

---

## 1. Orchestrator Agent

### What is it?

The Orchestrator Agent uses a **hub-and-spoke architecture** to intelligently route tasks to specialized agents via the A2A (Agent-to-Agent) protocol. It acts as a central coordinator that delegates work to the best agent for each subtask.

### Architecture

```mermaid
%% caption: The orchestrator routes each task to a specialist such as the Research Agent, Document Generator or Task Planner, then returns one consolidated result.
flowchart TD
    U["User request"] --> O["Orchestrator Agent"]
    O <-->|"task, result"| A1["Research Agent"]
    O <-->|"task, result"| A2["Document Generator"]
    O <-->|"task, result"| A3["Task Planner"]
    O --> R["Consolidated result to the user"]
    class O accent
```

### When to Use

 **Use Orchestrator Agent when:**
- You have complex multi-step tasks that require different specialized agents
- You need dynamic agent selection based on task requirements
- You want automatic result consolidation from multiple agents
- You're building enterprise-grade multi-agent systems

 **Don't use when:**
- You have a simple single-purpose task (use Custom Agent instead)
- You need agents to call other agents as tools (use Composable Agent instead)

### Example Use Case

**Research Report Generation**:
1. User: "Research AI trends and create a complete report"
2. Orchestrator routes to Research Agent → gathers papers
3. Orchestrator routes to Document Generator → creates report
4. Orchestrator routes to Task Planner → creates follow-up tasks
5. Orchestrator consolidates all results and returns to user

### Code Example

```typescript
// The Orchestrator Agent is a system agent - no code needed!
// Just use it via the UI or API

const result = await orpcClient.agents.execute({
  agentId: "orchestrator",
  message: "Research AI trends and create a detailed report",
  userId: session.user.id,
  organizationId: session.user.organizationId,
});
```

---

## 2. Fabric Composable Agent

### What is it?

The Composable Agent uses a **hierarchical architecture** where agents can call other agents as tools. It dynamically discovers agent capabilities via A2A protocol and composes complex workflows by chaining specialized agents.

### Architecture

```mermaid
%% caption: The composable agent discovers tools from Agent Cards in the agent registry and calls a research agent, which calls a document generator, which calls Notion MCP, with results returning up the chain to the user.
flowchart TD
    U["User request"] --> C["Composable Agent"]
    C <-->|"Agent Cards"| AR["Agent Registry"]
    C -->|"call as tool"| R["Research Agent"]
    R -->|"call as tool"| D["Document Generator"]
    D -->|"call as tool"| N["Notion MCP"]
    N -.->|"template"| D
    D -.->|"report"| R
    R -.->|"results"| C
    C --> F["Final output to the user"]
    class C accent
```

### Authentication Flow

The Composable Agent implements secure tenant context propagation for MCP credential lookup:

```mermaid
sequenceDiagram
    %% caption: The research agent passes user and organization context to the document generator, which looks up an access token and fetches a Notion template before returning a report.
    participant User
    participant ResearchAgent as Research Agent (A)
    participant DocGen as Document Generator (B)
    participant MCPConfig as MCPConfig DB
    participant Notion as Notion API

    User->>ResearchAgent: Create task (userId, orgId)

    Note over ResearchAgent: Research papers

    ResearchAgent->>DocGen: Call as tool (userId, orgId, variables)
    Note over DocGen: Receives tenant context

    DocGen->>MCPConfig: getMcpConfigForTenantAndServer(notion, userId, orgId)
    MCPConfig-->>DocGen: MCP credential record

    DocGen->>MCPConfig: getMcpAccessToken(configId, userId)
    MCPConfig-->>DocGen: Decrypted access token

    DocGen->>Notion: Fetch template with access token
    Notion-->>DocGen: Template data

    Note over DocGen: Generate report
    DocGen-->>ResearchAgent: Report markdown

    ResearchAgent-->>User: Task complete
```

### When to Use

 **Use Composable Agent when:**
- You need hierarchical agent systems (agents calling agents)
- You want dynamic tool discovery from Agent Cards
- You need automatic credential lookup for MCP tools
- You're building nested agent workflows

 **Don't use when:**
- You need simple hub-and-spoke delegation (use Orchestrator instead)
- You have a single-purpose task (use Custom Agent instead)

### Example Use Case

**Automated Research Pipeline**:
1. Composable Agent discovers available agents (Research, DocGen, Linear)
2. Calls Research Agent as tool → gathers papers
3. Research Agent calls DocGen as tool → creates report
4. DocGen calls Notion MCP as tool → fetches template
5. Results flow back up the hierarchy to user

### Code Example

```typescript
import {
  discoverAgentTools,
  executeAgentTool,
} from "@repo/agent-core";

// Discover tools from an agent
const tools = await discoverAgentTools("http://localhost:8080");

// Execute agent as tool with tenant context
const result = await executeAgentTool(
  tools[0],
  { format: "markdown" },
  {
    userId: session.user.id,
    organizationId: session.user.organizationId,
    executionId: "exec-123",
    variables: {
      research_papers: papers,
      key_findings: findings,
    },
  }
);
```

---

## 3. Custom Agents

### What are they?

Custom Agents are specialized agents you build yourself using various frameworks. Fabric supports multiple frameworks to give you flexibility in implementation.

### Supported Frameworks

#### LangGraph Agent
- **Best for**: Graph-based workflows, complex state management
- **Language**: Python/TypeScript
- **Features**: Checkpointing, streaming, custom nodes

#### Microsoft Agent (Semantic Kernel / AutoGen)
- **Best for**: Azure AI integration, Microsoft stack
- **Language**: C#/Python
- **Features**: Azure AI, Microsoft Graph, enterprise features

#### Pydantic AI Agent
- **Best for**: Type-safe Python workflows, structured outputs
- **Language**: Python
- **Features**: Strong typing, validation, Pydantic models

#### Fully Custom Agent
- **Best for**: Unique requirements, legacy integration
- **Language**: Any (via A2A protocol)
- **Features**: Complete flexibility, framework-agnostic

### When to Use

 **Use Custom Agent when:**
- You have specialized domain-specific requirements
- You need full control over agent logic and state
- You're integrating with specific frameworks or services
- You need advanced features like graph-based reasoning

 **Don't use when:**
- Standard orchestration patterns work (use Orchestrator)
- You need agent-as-tool composition (use Composable)

### Example: LangGraph Custom Agent

```typescript
// Define your custom LangGraph agent
import { StateGraph } from "@langchain/langgraph";

const workflow = new StateGraph({
  channels: {
    messages: { value: (x, y) => x.concat(y) },
    context: { value: (x, y) => ({ ...x, ...y }) },
  },
});

workflow.addNode("research", researchNode);
workflow.addNode("analyze", analyzeNode);
workflow.addNode("report", reportNode);

workflow.addEdge("research", "analyze");
workflow.addEdge("analyze", "report");

const app = workflow.compile();

// Register as Custom Agent in Fabric
await orpcClient.agents.registry.create({
  name: "research-analyst",
  displayName: "Research Analyst",
  description: "Specialized agent for academic research analysis",
  framework: "LANGGRAPH",
  scope: "USER",
  config: {
    graphId: "research-analyst",
    model: "gpt-4o",
    systemPromptKey: "research-analyst-prompt",
  },
});
```

---

## Decision Matrix: Which Agent Type Should I Use?

Use this decision tree to choose the right agent type:

```mermaid
%% caption: A multi-step task goes to the Orchestrator Agent, or to the Composable Agent when it needs hierarchical agent calls, and everything else becomes a Custom Agent.
flowchart TD
    M{"Multi-step task with coordination?"} -->|"yes"| H{"Need hierarchical agent calls?"}
    M -->|"no"| X["Use Custom Agent"]
    H -->|"yes"| C["Use Composable Agent"]
    H -->|"no"| O["Use Orchestrator Agent"]
    class O accent
```

---

## Best Practices

### 1. Start Simple
- Begin with Orchestrator Agent for most multi-agent workflows
- Only use Composable Agent when you truly need hierarchical composition
- Use Custom Agents for specialized tasks that don't fit standard patterns

### 2. Use A2A Protocol
- All agents communicate via A2A protocol for interoperability
- Agent Cards provide automatic tool discovery
- Tenant context propagation ensures secure credential access

### 3. Security Considerations
- Never pass credentials in A2A messages
- Always use tenant context (userId/organizationId) for credential lookup
- Implement proper authorization checks in custom agents

### 4. Performance Optimization
- Use parallel execution when tasks are independent
- Implement caching for frequently accessed data
- Monitor agent execution times and optimize bottlenecks

---

## Getting Started

### Creating an Orchestrator Agent

1. Go to **Agents** → **Create Agent**
2. Select **Orchestrator Agent** under System Agents
3. Configure scope (User or Organization)
4. Add MCP servers for tool access
5. Start using immediately!

### Creating a Composable Agent

1. Go to **Agents** → **Create Agent**
2. Select **Composable Agent** under System Agents
3. Configure available agents to compose
4. Set up tenant context propagation
5. Test hierarchical workflows

### Creating a Custom Agent

1. Go to **Agents** → **Create Agent**
2. Select **Custom Agent**
3. Choose framework (LangGraph, Microsoft, Pydantic AI, or Custom)
4. Implement your agent logic
5. Deploy and register with Fabric

---

## Conclusion

Fabric's three agent types provide flexibility for any use case:

- **Orchestrator Agent** for multi-step coordination
- **Composable Agent** for hierarchical agent systems
- **Custom Agents** for specialized domain tasks

Choose the right agent type based on your requirements, and use Fabric's A2A protocol for smooth multi-agent communication.

## Frequently asked questions

### Do I need to write code to use the Orchestrator Agent?

No. It's a system agent, so you create it under Agents > Create Agent and call it from the UI or through the API with `agentId: "orchestrator"`. What it can reach depends on the MCP servers you add when you set it up, so add one for each tool you'll want it to use.

### How does a Composable Agent use my Notion account without my credentials in the messages?

Each agent passes your user and organization IDs down the chain instead of a token. The agent that needs Notion looks up the MCP credential record for that tenant and server, then gets the decrypted access token from it. So the Notion MCP server has to be configured for the user or organization running the task, or the lookup has nothing to find.

### Can I build a custom agent in a framework Fabric doesn't list?

Yes. A fully custom agent can be written in any language, as long as it speaks the A2A protocol, and you register it with Fabric once it's deployed. Speaking A2A is also what lets the other agents work with it, since a Composable Agent finds tools through Agent Cards.

### When should I move from the Orchestrator Agent to a Composable Agent?

Move when one specialist needs to call another in the middle of its own task. Under the Orchestrator, every specialist hands its result back to the hub, so the research agent can't ask the document generator for anything directly. Under the Composable Agent, it calls the document generator as a tool, and the document generator can call Notion MCP in turn.

## Further reading

- [Orchestrator Agent Documentation](https://fabric.pro/en/docs/agents/orchestrator)
- [Agent types overview](https://fabric.pro/en/docs/agents/overview)
- [Agent templates guide](https://fabric.pro/en/docs/features/agent-templates)
- [A2A Protocol Specification](https://a2a-protocol.org/latest/specification/)
- [MCP Integration Guide](https://fabric.pro/en/docs/integrations/mcp)

---

*Have questions? Check out the [GitHub repository](https://github.com/Fabric-Pro/fabric-oss).*
