diff --git a/agents-api/agents_api/autogen/Common.py b/agents-api/agents_api/autogen/Common.py index cb8d88035..a2d6b99a6 100644 --- a/agents-api/agents_api/autogen/Common.py +++ b/agents-api/agents_api/autogen/Common.py @@ -9,6 +9,16 @@ from pydantic import AwareDatetime, BaseModel, ConfigDict, Field, RootModel +class JinjaTemplate(RootModel[str]): + model_config = ConfigDict( + populate_by_name=True, + ) + root: str + """ + A valid jinja template. + """ + + class Limit(RootModel[int]): model_config = ConfigDict( populate_by_name=True, diff --git a/agents-api/agents_api/autogen/Sessions.py b/agents-api/agents_api/autogen/Sessions.py index f167efec5..5eb866134 100644 --- a/agents-api/agents_api/autogen/Sessions.py +++ b/agents-api/agents_api/autogen/Sessions.py @@ -43,6 +43,16 @@ class CreateSessionRequest(BaseModel): """ Action to start on context window overflow """ + forward_tool_results: Literal["auto"] | StrictBool = "auto" + """ + Whether to forward the tool results to the model when available. + "true" => always forward + "false" => never forward + "auto" => forward if applicable + + If a tool call is made, the tool's output will be sent back to the model as the model's input. + If a tool call is not made, the model's output will be returned as is. + """ metadata: dict[str, Any] | None = None @@ -70,6 +80,16 @@ class PatchSessionRequest(BaseModel): """ Action to start on context window overflow """ + forward_tool_results: Literal["auto"] | StrictBool = "auto" + """ + Whether to forward the tool results to the model when available. + "true" => always forward + "false" => never forward + "auto" => forward if applicable + + If a tool call is made, the tool's output will be sent back to the model as the model's input. + If a tool call is not made, the model's output will be returned as is. + """ metadata: dict[str, Any] | None = None @@ -97,6 +117,16 @@ class Session(BaseModel): """ Action to start on context window overflow """ + forward_tool_results: Literal["auto"] | StrictBool = "auto" + """ + Whether to forward the tool results to the model when available. + "true" => always forward + "false" => never forward + "auto" => forward if applicable + + If a tool call is made, the tool's output will be sent back to the model as the model's input. + If a tool call is not made, the model's output will be returned as is. + """ id: Annotated[UUID, Field(json_schema_extra={"readOnly": True})] metadata: dict[str, Any] | None = None created_at: Annotated[AwareDatetime, Field(json_schema_extra={"readOnly": True})] @@ -160,6 +190,16 @@ class UpdateSessionRequest(BaseModel): """ Action to start on context window overflow """ + forward_tool_results: Literal["auto"] | StrictBool = "auto" + """ + Whether to forward the tool results to the model when available. + "true" => always forward + "false" => never forward + "auto" => forward if applicable + + If a tool call is made, the tool's output will be sent back to the model as the model's input. + If a tool call is not made, the model's output will be returned as is. + """ metadata: dict[str, Any] | None = None @@ -194,6 +234,16 @@ class CreateOrUpdateSessionRequest(CreateSessionRequest): """ Action to start on context window overflow """ + forward_tool_results: Literal["auto"] | StrictBool = "auto" + """ + Whether to forward the tool results to the model when available. + "true" => always forward + "false" => never forward + "auto" => forward if applicable + + If a tool call is made, the tool's output will be sent back to the model as the model's input. + If a tool call is not made, the model's output will be returned as is. + """ metadata: dict[str, Any] | None = None diff --git a/agents-api/agents_api/autogen/Tasks.py b/agents-api/agents_api/autogen/Tasks.py index c1e69d492..2b5318c0c 100644 --- a/agents-api/agents_api/autogen/Tasks.py +++ b/agents-api/agents_api/autogen/Tasks.py @@ -15,7 +15,7 @@ TextOnlyDocSearchRequest, VectorDocSearchRequest, ) -from .Tools import CreateToolRequest +from .Tools import CreateToolRequest, NamedToolChoice class CaseThen(BaseModel): @@ -46,6 +46,34 @@ class CaseThen(BaseModel): """ +class CaseThenUpdateItem(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + case: Literal["_"] | str + """ + The condition to evaluate + """ + then: ( + EvaluateStep + | ToolCallStep + | PromptStepUpdateItem + | GetStep + | SetStep + | LogStep + | EmbedStep + | SearchStep + | ReturnStep + | SleepStep + | ErrorWorkflowStep + | YieldStep + | WaitForInputStep + ) + """ + The steps to run if the condition is true + """ + + class Content(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -74,6 +102,14 @@ class ContentModel(BaseModel): """ +class ContentModel1(Content): + pass + + +class ContentModel2(ContentModel): + pass + + class CreateTaskRequest(BaseModel): """ Payload for creating a task @@ -197,6 +233,30 @@ class ForeachDo(BaseModel): """ +class ForeachDoUpdateItem(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + in_: Annotated[str, Field(alias="in")] + """ + The variable to iterate over. + VALIDATION: Should NOT return more than 1000 elements. + """ + do: ( + EvaluateStep + | ToolCallStep + | PromptStepUpdateItem + | GetStep + | SetStep + | LogStep + | EmbedStep + | SearchStep + ) + """ + The steps to run for each iteration + """ + + class ForeachStep(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -213,6 +273,20 @@ class ForeachStep(BaseModel): """ +class ForeachStepUpdateItem(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + kind_: str | None = None + """ + Discriminator property for BaseWorkflowStep. + """ + foreach: ForeachDoUpdateItem + """ + The steps to run for each iteration + """ + + class GetStep(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -281,6 +355,58 @@ class IfElseWorkflowStep(BaseModel): """ +class IfElseWorkflowStepUpdateItem(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + kind_: str | None = None + """ + Discriminator property for BaseWorkflowStep. + """ + if_: Annotated[str, Field(alias="if")] + """ + The condition to evaluate + """ + then: ( + EvaluateStep + | ToolCallStep + | PromptStepUpdateItem + | GetStep + | SetStep + | LogStep + | EmbedStep + | SearchStep + | ReturnStep + | SleepStep + | ErrorWorkflowStep + | YieldStep + | WaitForInputStep + ) + """ + The steps to run if the condition is true + """ + else_: Annotated[ + EvaluateStep + | ToolCallStep + | PromptStepUpdateItem + | GetStep + | SetStep + | LogStep + | EmbedStep + | SearchStep + | ReturnStep + | SleepStep + | ErrorWorkflowStep + | YieldStep + | WaitForInputStep + | None, + Field(None, alias="else"), + ] + """ + The steps to run if the condition is false + """ + + class ImageUrl(BaseModel): """ The image URL @@ -371,7 +497,7 @@ class MainModel(BaseModel): map: ( EvaluateStep | ToolCallStep - | PromptStep + | PromptStepUpdateItem | GetStep | SetStep | LogStep @@ -425,6 +551,32 @@ class ParallelStep(BaseModel): """ +class ParallelStepUpdateItem(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + kind_: str | None = None + """ + Discriminator property for BaseWorkflowStep. + """ + parallel: Annotated[ + list[ + EvaluateStep + | ToolCallStep + | PromptStepUpdateItem + | GetStep + | SetStep + | LogStep + | EmbedStep + | SearchStep + ], + Field(max_length=100), + ] + """ + The steps to run in parallel. Max concurrency will depend on the platform. + """ + + class PatchTaskRequest(BaseModel): """ Payload for patching a task @@ -438,7 +590,7 @@ class PatchTaskRequest(BaseModel): list[ EvaluateStep | ToolCallStep - | PromptStep + | PromptStepUpdateItem | GetStep | SetStep | LogStep @@ -449,10 +601,10 @@ class PatchTaskRequest(BaseModel): | ErrorWorkflowStep | YieldStep | WaitForInputStep - | IfElseWorkflowStep - | SwitchStep - | ForeachStep - | ParallelStep + | IfElseWorkflowStepUpdateItem + | SwitchStepUpdateItem + | ForeachStepUpdateItem + | ParallelStepUpdateItem | MainModel ] | None, @@ -520,10 +672,72 @@ class PromptStep(BaseModel): """ The prompt to run """ + tools: Literal["all"] | list[ToolRef | CreateToolRequest] = [] + """ + The tools to use for the prompt + """ + tool_choice: Literal["auto", "none"] | NamedToolChoice | None = None + """ + The tool choice for the prompt + """ + settings: ChatSettings | None = None + """ + Settings for the prompt + """ + unwrap: StrictBool = False + """ + Whether to unwrap the output of the prompt step, equivalent to `response.choices[0].message.content` + """ + forward_tool_results: Literal["auto"] | StrictBool = "auto" + """ + Whether to forward the tool results to the model when available. + "true" => always forward + "false" => never forward + "auto" => forward if applicable + + If a tool call is made, the tool's output will be used as the model's input. + If a tool call is not made, the model's output will be used as the next step's input. + """ + + +class PromptStepUpdateItem(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + kind_: str | None = None + """ + Discriminator property for BaseWorkflowStep. + """ + prompt: list[PromptItem] | str + """ + The prompt to run + """ + tools: Literal["all"] | list[ToolRefUpdateItem | CreateToolRequest] = [] + """ + The tools to use for the prompt + """ + tool_choice: Literal["auto", "none"] | NamedToolChoice | None = None + """ + The tool choice for the prompt + """ settings: ChatSettings | None = None """ Settings for the prompt """ + unwrap: StrictBool = False + """ + Whether to unwrap the output of the prompt step, equivalent to `response.choices[0].message.content` + """ + forward_tool_results: Literal["auto"] | StrictBool = "auto" + """ + Whether to forward the tool results to the model when available. + "true" => always forward + "false" => never forward + "auto" => forward if applicable + + If a tool call is made, the tool's output will be used as the model's input. + If a tool call is not made, the model's output will be used as the next step's input. + """ class ReturnStep(BaseModel): @@ -626,6 +840,20 @@ class SwitchStep(BaseModel): """ +class SwitchStepUpdateItem(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + kind_: str | None = None + """ + Discriminator property for BaseWorkflowStep. + """ + switch: Annotated[list[CaseThenUpdateItem], Field(min_length=1)] + """ + The cond tree + """ + + class Task(BaseModel): """ Object describing a Task @@ -706,9 +934,7 @@ class ToolCallStep(BaseModel): """ The kind of step """ - tool: Annotated[ - str, Field(pattern="^(function|integration|system|api_call)\\.(\\w+)$") - ] + tool: Annotated[str, Field(max_length=40, pattern="^[^\\W0-9]\\w*$")] """ The tool to run """ @@ -718,6 +944,52 @@ class ToolCallStep(BaseModel): """ +class ToolRef(BaseModel): + """ + Reference to a tool + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + ref: ToolRefById | ToolRefByName + + +class ToolRefById(BaseModel): + """ + Reference to a tool by id + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + id: UUID | None = None + + +class ToolRefByName(BaseModel): + """ + Reference to a tool by name + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + name: Annotated[str | None, Field(None, max_length=40, pattern="^[^\\W0-9]\\w*$")] + """ + Valid python identifier names + """ + + +class ToolRefUpdateItem(BaseModel): + """ + Reference to a tool + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + + class UpdateTaskRequest(BaseModel): """ Payload for updating a task diff --git a/agents-api/agents_api/autogen/Tools.py b/agents-api/agents_api/autogen/Tools.py index f18e8fe71..7b7f38214 100644 --- a/agents-api/agents_api/autogen/Tools.py +++ b/agents-api/agents_api/autogen/Tools.py @@ -22,9 +22,6 @@ class ChosenToolCall(BaseModel): Whether this tool is a `function`, `api_call`, `system` etc. (Only `function` tool supported right now) """ function: FunctionCallOption | None = None - integration: Any | None = None - system: Any | None = None - api_call: Any | None = None id: Annotated[UUID, Field(json_schema_extra={"readOnly": True})] @@ -50,7 +47,6 @@ class CreateToolRequest(BaseModel): """ integration: IntegrationDef | None = None system: SystemDef | None = None - api_call: Any | None = None class FunctionCallOption(BaseModel): @@ -93,7 +89,17 @@ class IntegrationDef(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - provider: str + provider: Literal[ + "dummy", + "dall-e", + "duckduckgo", + "hackernews", + "weather", + "wikipedia", + "twitter", + "webpage", + "requests", + ] """ The provider of the integration """ @@ -123,7 +129,20 @@ class IntegrationDefUpdate(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - provider: str | None = None + provider: ( + Literal[ + "dummy", + "dall-e", + "duckduckgo", + "hackernews", + "weather", + "wikipedia", + "twitter", + "webpage", + "requests", + ] + | None + ) = None """ The provider of the integration """ @@ -154,9 +173,6 @@ class NamedToolChoice(BaseModel): Whether this tool is a `function`, `api_call`, `system` etc. (Only `function` tool supported right now) """ function: FunctionCallOption | None = None - integration: Any | None = None - system: Any | None = None - api_call: Any | None = None class PatchToolRequest(BaseModel): @@ -181,7 +197,6 @@ class PatchToolRequest(BaseModel): """ integration: IntegrationDefUpdate | None = None system: SystemDefUpdate | None = None - api_call: Any | None = None class SystemDef(BaseModel): @@ -246,7 +261,6 @@ class Tool(BaseModel): """ integration: IntegrationDef | None = None system: SystemDef | None = None - api_call: Any | None = None created_at: Annotated[AwareDatetime, Field(json_schema_extra={"readOnly": True})] """ When this resource was created as UTC date-time @@ -291,7 +305,6 @@ class UpdateToolRequest(BaseModel): """ integration: IntegrationDef | None = None system: SystemDef | None = None - api_call: Any | None = None class ChosenFunctionCall(ChosenToolCall): diff --git a/typespec/common/scalars.tsp b/typespec/common/scalars.tsp index 79eda2d99..97fe37706 100644 --- a/typespec/common/scalars.tsp +++ b/typespec/common/scalars.tsp @@ -48,12 +48,21 @@ alias eventStream = "text/event-stream"; /** Different possible sources that can produce new entries */ alias entrySource = "api_request" | "api_response" | "tool_response" | "internal" | "summarizer" | "meta"; -/** Naming convention for tool references. Tools are resolved in order: `step-settings` -> `task` -> `agent` */ -@pattern("^(function|integration|system|api_call)\\.(\\w+)$") -scalar toolRef extends string; - /** A simple python expression compatible with SimpleEval. */ scalar PyExpression extends string; /** A valid jinja template. */ -scalar JinjaTemplate extends string; \ No newline at end of file +scalar JinjaTemplate extends string; + +/** Integration provider name */ +alias integrationProvider = ( + | "dummy" + | "dall-e" + | "duckduckgo" + | "hackernews" + | "weather" + | "wikipedia" + | "twitter" + | "webpage" + | "requests" +); diff --git a/typespec/sessions/models.tsp b/typespec/sessions/models.tsp index aecec4ba1..89678e926 100644 --- a/typespec/sessions/models.tsp +++ b/typespec/sessions/models.tsp @@ -62,6 +62,15 @@ model Session { /** Action to start on context window overflow */ context_overflow: ContextOverflowType | null = null; + /** Whether to forward the tool results to the model when available. + * "true" => always forward + * "false" => never forward + * "auto" => forward if applicable + * + * If a tool call is made, the tool's output will be sent back to the model as the model's input. + * If a tool call is not made, the model's output will be returned as is. */ + forward_tool_results: "auto" | boolean = "auto"; + ...HasId; ...HasMetadata; ...HasTimestamps; diff --git a/typespec/tasks/models.tsp b/typespec/tasks/models.tsp index 4ec23f31b..b8b115861 100644 --- a/typespec/tasks/models.tsp +++ b/typespec/tasks/models.tsp @@ -30,6 +30,24 @@ model TaskTool extends CreateToolRequest { inherited?: boolean = false; } +/** Reference to a tool by id */ +model ToolRefById { + @visibility("read", "create") + id?: uuid; +} + +/** Reference to a tool by name */ +model ToolRefByName { + @visibility("read", "create") + name?: validPythonIdentifier; +} + +/** Reference to a tool */ +model ToolRef { + @visibility("read", "create") + ref: ToolRefById | ToolRefByName; +} + /** Object describing a Task */ model Task { @visibility("read", "create") diff --git a/typespec/tasks/steps.tsp b/typespec/tasks/steps.tsp index d9be46577..abfbbc5ed 100644 --- a/typespec/tasks/steps.tsp +++ b/typespec/tasks/steps.tsp @@ -4,6 +4,7 @@ import "../chat"; import "../common"; import "../docs"; import "../entries"; +import "../tools"; import "./step_kind.tsp"; @@ -13,6 +14,7 @@ using Chat; using Common; using Docs; using Entries; +using Tools; namespace Tasks; @@ -76,7 +78,7 @@ model ToolCallStep extends BaseWorkflowStep<"tool_call"> { model ToolCallStepDef { /** The tool to run */ - tool: toolRef; + tool: validPythonIdentifier; /** The input parameters for the tool (defaults to last step output) */ arguments: ExpressionObject | "_" = "_"; @@ -93,8 +95,26 @@ model PromptStepDef { /** The prompt to run */ prompt: JinjaTemplate | InputChatMLMessage[]; + /** The tools to use for the prompt */ + tools: "all" | (ToolRef | CreateToolRequest)[] = #[]; + + /** The tool choice for the prompt */ + tool_choice?: ToolChoiceOption; + /** Settings for the prompt */ settings?: ChatSettings; + + /** Whether to unwrap the output of the prompt step, equivalent to `response.choices[0].message.content` */ + unwrap?: boolean = false; + + /** Whether to forward the tool results to the model when available. + * "true" => always forward + * "false" => never forward + * "auto" => forward if applicable + * + * If a tool call is made, the tool's output will be used as the model's input. + * If a tool call is not made, the model's output will be used as the next step's input. */ + forward_tool_results: "auto" | boolean = "auto"; } model EvaluateStep extends BaseWorkflowStep<"evaluate"> { diff --git a/typespec/tools/models.tsp b/typespec/tools/models.tsp index 953238508..b7478ee24 100644 --- a/typespec/tools/models.tsp +++ b/typespec/tools/models.tsp @@ -45,7 +45,7 @@ model FunctionDef { /** Integration definition */ model IntegrationDef { /** The provider of the integration */ - provider: string; + provider: integrationProvider; /** The specific method of the integration to call */ method?: string; @@ -84,7 +84,7 @@ model Tool { function?: FunctionDef; integration?: IntegrationDef; system?: SystemDef; - api_call?: unknown; + api_call?: never; // TODO: Implement ...HasTimestamps; ...HasId; @@ -101,9 +101,9 @@ model NamedToolChoice { type: ToolType; function?: FunctionCallOption; - integration?: unknown; - system?: unknown; - api_call?: unknown; + integration?: never; // TODO: Implement + system?: never; // TODO: Implement + api_call?: never; // TODO: Implement } model NamedFunctionChoice extends NamedToolChoice { @@ -142,9 +142,9 @@ model ChosenToolCall { type: ToolType; function?: FunctionCallOption; - integration?: unknown; - system?: unknown; - api_call?: unknown; + integration?: never; // TODO: Implement + system?: never; // TODO: Implement + api_call?: never; // TODO: Implement ...HasId; }