feat: Add support for agent handoffs with edges in agent forms and schemas

This commit is contained in:
Danny Avila 2025-09-03 21:15:31 -04:00
parent e705b09280
commit 317a5b5310
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
12 changed files with 406 additions and 3 deletions

View file

@ -38,6 +38,17 @@ export const agentSupportContactSchema = z
})
.optional();
/** Graph edge schema for agent handoffs */
export const graphEdgeSchema = z.object({
from: z.union([z.string(), z.array(z.string())]),
to: z.union([z.string(), z.array(z.string())]),
description: z.string().optional(),
edgeType: z.enum(['handoff', 'direct']).optional(),
prompt: z.union([z.string(), z.function()]).optional(),
excludeResults: z.boolean().optional(),
promptKey: z.string().optional(),
});
/** Base agent schema with all common fields */
export const agentBaseSchema = z.object({
name: z.string().nullable().optional(),
@ -47,6 +58,7 @@ export const agentBaseSchema = z.object({
model_parameters: z.record(z.unknown()).optional(),
tools: z.array(z.string()).optional(),
agent_ids: z.array(z.string()).optional(),
edges: z.array(graphEdgeSchema).optional(),
end_after_tools: z.boolean().optional(),
hide_sequential_outputs: z.boolean().optional(),
artifacts: z.string().optional(),

View file

@ -176,6 +176,7 @@ export const defaultAgentFormValues = {
tools: [],
provider: {},
projectIds: [],
edges: [],
artifacts: '',
/** @deprecated Use ACL permissions instead */
isCollaborative: false,

View file

@ -355,3 +355,45 @@ export type AgentToolType = {
} & ({ assistant_id: string; agent_id?: never } | { assistant_id?: never; agent_id?: string });
export type ToolMetadata = TPlugin;
export interface BaseMessage {
content: string;
role?: string;
[key: string]: unknown;
}
export interface BaseGraphState {
[key: string]: unknown;
}
export type GraphEdge = {
/** Agent ID, use a list for multiple sources */
from: string | string[];
/** Agent ID, use a list for multiple destinations */
to: string | string[];
description?: string;
/** Can return boolean or specific destination(s) */
condition?: (state: BaseGraphState) => boolean | string | string[];
/** 'handoff' creates tools for dynamic routing, 'direct' creates direct edges, which also allow parallel execution */
edgeType?: 'handoff' | 'direct';
/**
* For direct edges: Optional prompt to add when transitioning through this edge.
* String prompts can include variables like {results} which will be replaced with
* messages from startIndex onwards. When {results} is used, excludeResults defaults to true.
*
* For handoff edges: Description for the input parameter that the handoff tool accepts,
* allowing the supervisor to pass specific instructions/context to the transferred agent.
*/
prompt?: string | ((messages: BaseMessage[], runStartIndex: number) => string | undefined);
/**
* When true, excludes messages from startIndex when adding prompt.
* Automatically set to true when {results} variable is used in prompt.
*/
excludeResults?: boolean;
/**
* For handoff edges: Customizes the parameter name for the handoff input.
* Defaults to "instructions" if not specified.
* Only applies when prompt is provided for handoff edges.
*/
promptKey?: string;
};

View file

@ -1,7 +1,7 @@
import type { OpenAPIV3 } from 'openapi-types';
import type { AssistantsEndpoint, AgentProvider } from 'src/schemas';
import type { Agents, GraphEdge } from './agents';
import type { ContentTypes } from './runs';
import type { Agents } from './agents';
import type { TFile } from './files';
import { ArtifactModes } from 'src/artifacts';
@ -226,6 +226,7 @@ export type Agent = {
isCollaborative?: boolean;
tool_resources?: AgentToolResources;
agent_ids?: string[];
edges?: GraphEdge[];
end_after_tools?: boolean;
hide_sequential_outputs?: boolean;
artifacts?: ArtifactModes;
@ -251,6 +252,7 @@ export type AgentCreateParams = {
} & Pick<
Agent,
| 'agent_ids'
| 'edges'
| 'end_after_tools'
| 'hide_sequential_outputs'
| 'artifacts'
@ -276,6 +278,7 @@ export type AgentUpdateParams = {
} & Pick<
Agent,
| 'agent_ids'
| 'edges'
| 'end_after_tools'
| 'hide_sequential_outputs'
| 'artifacts'

View file

@ -71,6 +71,10 @@ const agentSchema = new Schema<IAgent>(
agent_ids: {
type: [String],
},
edges: {
type: [{ type: Schema.Types.Mixed }],
default: [],
},
isCollaborative: {
type: Boolean,
default: undefined,

View file

@ -1,4 +1,5 @@
import { Document, Types } from 'mongoose';
import type { GraphEdge } from 'librechat-data-provider';
export interface ISupportContact {
name?: string;
@ -28,6 +29,7 @@ export interface IAgent extends Omit<Document, 'model'> {
hide_sequential_outputs?: boolean;
end_after_tools?: boolean;
agent_ids?: string[];
edges?: GraphEdge[];
/** @deprecated Use ACL permissions instead */
isCollaborative?: boolean;
conversation_starters?: string[];