Skip to main content

Agent Teams (Multi-Agent)

An Agent Team is a group of specialized agents deployed behind one chat app. Each agent has its own model, prompt, tools, examples, and optional data sources, and the team coordinates them.

Same feature, different name

The TypeScript SDK calls this an Agent Team (AgentTeam). The Python SDK calls the same backend feature a Custodian Squad (CustodianSquad).

When to use an Agent Team

  • Different questions should be handled by different instructions.
  • Each agent has a clear topic area.
  • One agent needs a data source the others do not.
  • You want the response to show which agent handled the request.

For a single agent with one prompt, use the Custodian Agent Class.

Core objects

ObjectPurpose
AgentA team member: model, prompt, topics, tools, examples, response schema, optional data source files.
AgentTeamGroups agents and defines the routing mode and connection config.
TeamAppThe deployed team app returned by team.deploy(). Use it to chat.

Create a team

import { Agent, AgentTeam } from "@custodianlabs/sdk";

const team = new AgentTeam({
agents: [
new Agent({
name: "billing",
model: "gpt-4o",
systemPrompt: "Answer billing questions.",
topics: ["billing", "invoice", "refund", "payment"],
}),
new Agent({
name: "data",
model: "gpt-4o",
systemPrompt: "Answer questions about the uploaded CSV file.",
topics: ["data", "csv", "customer", "file"],
}).addDataSourceFile("./data/customers.csv"),
],
routingMode: "single",
});

const app = await team.deploy();

const reply = await app.chat("I have a question about my invoice.");
console.log(reply?.response);
console.log(reply?.selectedAgent);

Agent options

OptionNotes
nameRequired. Unique within the team.
modelRequired.
systemPromptRequired.
topicsKeywords used for routing.
canHandoffToAgent names this agent may hand off to. chain mode only.
descriptionMetadata.
toolsBuilt-in tools for this agent. See Built-in Tools.
examplesFew-shot examples for this agent.
outputKeyIn workflow mode, the key this agent's output is stored under.
inputSchema / responseSchemaJSON Schema for this agent.
privacyEnabledInline PII masking for this agent. Default false.

agent.addDataSourceFile(file) and agent.setPriority(n) return the agent for chaining.

AgentTeam options

OptionNotes
agentsRequired. At least one, with unique names.
routingMode"single" (default), "chain", or "workflow".
maxHandoffschain mode only. Default 4.
workflowOrderRequired when routingMode is "workflow": agent names in run order.
name / descriptionMetadata.
inputSchema / responseSchemaTeam-level JSON Schema. In workflow mode, responseSchema governs the final output.
apiKey / baseUrl / timeout / maxRetriesConnection config for the whole team.
Difference from the Python SDK

Python puts api_key / base_url on each member and reconciles them. The TypeScript SDK puts connection config directly on AgentTeam, since a team has one connection.

Routing modes

ModeBehaviorUse when
singleOne agent is selected per message from topics.Most teams — one specialist per message.
chainAgents hand off to each other via canHandoffTo, up to maxHandoffs.Conversations where agents pass work between each other.
workflowAgents run in the fixed workflowOrder; each output feeds the next.Deterministic multi-step pipelines.

Handoffs are chain-only. canHandoffTo and maxHandoffs are ignored in single and workflow modes.

Chain mode

const team = new AgentTeam({
agents: [
new Agent({
name: "triage",
model: "gpt-4o",
systemPrompt: "Classify the issue.",
topics: ["billing", "support"],
canHandoffTo: ["expert"],
}),
new Agent({ name: "expert", model: "gpt-4o", systemPrompt: "Resolve the issue." }),
],
routingMode: "chain",
maxHandoffs: 3,
});

const app = await team.deploy();
const reply = await app.chat("A payment is stuck. Investigate it.");
console.log(reply?.handoffPath); // e.g. ["triage", "expert"]

Workflow mode

const team = new AgentTeam({
agents: [
new Agent({
name: "research",
model: "gpt-4o",
systemPrompt: "Research the topic.",
tools: ["web_search"],
outputKey: "research_notes",
}),
new Agent({
name: "writer",
model: "gpt-4o",
systemPrompt: "Write a summary from the research notes.",
}),
],
routingMode: "workflow",
workflowOrder: ["research", "writer"],
});

Validation

new AgentTeam(...) throws before any network call when:

  • agents is empty.
  • Two agents share a name.
  • routingMode is "workflow" without a non-empty workflowOrder.
  • workflowOrder names an agent that is not in agents.

Chat with a team

TeamApp.chat() retains the session like a single-agent App:

const reply = await app.chat("Can you help with a refund question?");
console.log(reply?.response);
console.log(reply?.selectedAgent); // which agent answered
console.log(reply?.handoffPath); // chain mode
console.log(reply?.contributingAgents); // workflow mode

app.sessionId, app.resetSession(), and interactive app.chat() behave the same as for a single Custodian Agent — see Chat Sessions.

Data sources per agent

Attach a file to the agent that should use it:

new Agent({
name: "data",
model: "gpt-4o",
systemPrompt: "Answer questions about the uploaded CSV file.",
}).addDataSourceFile("./data/customers.csv");

Staged files upload after the team is created, during .deploy().

Sharing

Configured at deploy time on the team, never on the agents:

await team.deploy(); // public (default)
await team.deploy({ shareMode: "private" });
await team.deploy({ shareMode: "password", sharePassword: "s3cret" });

Next steps