mirror of
https://github.com/openai/codex.git
synced 2026-09-13 11:47:17 +00:00
not optional
This commit is contained in:
@@ -2153,11 +2153,10 @@ async fn handle_function_call(
|
||||
|
||||
match result {
|
||||
Ok(message) => {
|
||||
// If this subagent declares an output schema, validate against it and
|
||||
// return the JSON body unmodified. Otherwise fallback to envelope for text.
|
||||
if let Some(def) = turn_context.subagents_registry.get(&agent_name)
|
||||
&& let Some(schema) = def.output_schema()
|
||||
{
|
||||
// Validate against the subagent's output schema and return
|
||||
// the JSON body unmodified.
|
||||
if let Some(def) = turn_context.subagents_registry.get(&agent_name) {
|
||||
let schema = def.output_schema();
|
||||
match serde_json::from_str::<serde_json::Value>(&message) {
|
||||
Ok(val) => {
|
||||
if let Err(err) =
|
||||
@@ -2195,24 +2194,14 @@ async fn handle_function_call(
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// No schema: best-effort envelope
|
||||
let json_payload = match serde_json::from_str::<serde_json::Value>(&message)
|
||||
{
|
||||
Ok(val) => serde_json::json!({
|
||||
"subagent": agent_name,
|
||||
"output": val,
|
||||
}),
|
||||
Err(_) => serde_json::json!({
|
||||
"subagent": agent_name,
|
||||
"output": { "type": "text", "message": message },
|
||||
}),
|
||||
};
|
||||
let content = serde_json::to_string(&json_payload).unwrap_or(message);
|
||||
ResponseInputItem::FunctionCallOutput {
|
||||
call_id,
|
||||
output: FunctionCallOutputPayload {
|
||||
content,
|
||||
success: Some(true),
|
||||
content: format!(
|
||||
"subagent not found when validating output: {}",
|
||||
agent_name
|
||||
),
|
||||
success: Some(false),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "hello",
|
||||
"description": "Built-in test subagent that replies with a greeting",
|
||||
"instructions": "Reply with exactly this text and nothing else: Hello from subagent",
|
||||
"instructions": "Reply with exactly this text and nothing else, as a JSON string: Hello from subagent",
|
||||
"output_schema": { "type": "string" },
|
||||
"tools": [],
|
||||
"reasoning_effort": "minimal"
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,10 @@ pub struct SubagentDefinition {
|
||||
pub instructions: String,
|
||||
|
||||
//TODO: add allowed tools. we inherit the parent agent's tools for now.
|
||||
/// Optional structured output schema. When set, the subagent must return a
|
||||
/// single JSON value that validates against this schema. The schema will be
|
||||
/// embedded into the subagent's instructions so the model can adhere to it.
|
||||
#[serde(default)]
|
||||
output_schema: Option<JsonSchema>,
|
||||
/// Structured output schema. The subagent must return a single JSON value
|
||||
/// that validates against this schema. The schema will be embedded into the
|
||||
/// subagent's instructions so the model can adhere to it.
|
||||
output_schema: JsonSchema,
|
||||
|
||||
/// Optional model override for this subagent. When not provided, inherits
|
||||
/// the parent session's configured model.
|
||||
@@ -59,7 +58,7 @@ impl SubagentDefinition {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn output_schema(&self) -> Option<&JsonSchema> {
|
||||
self.output_schema.as_ref()
|
||||
pub(crate) fn output_schema(&self) -> &JsonSchema {
|
||||
&self.output_schema
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,24 +19,20 @@ pub struct RunSubagentArgs {
|
||||
///
|
||||
/// For user- and project-scoped subagents, we append their instructions to the
|
||||
/// parent session's base instructions. For embedded defaults, we use only the
|
||||
/// subagent's instructions. If an output schema is present, we augment the
|
||||
/// subagent instructions with strict JSON output requirements.
|
||||
/// subagent's instructions. We always augment the subagent instructions with
|
||||
/// strict JSON output requirements based on its schema.
|
||||
fn compose_base_instructions_for_subagent(
|
||||
def: &SubagentDefinition,
|
||||
parent_base_instructions: Option<&str>,
|
||||
) -> String {
|
||||
// Start with the subagent's own instructions, optionally augmented with
|
||||
// structured output requirements.
|
||||
let child_instructions = if let Some(schema) = def.output_schema() {
|
||||
let schema_json = serde_json::to_string_pretty(schema).unwrap_or_else(|_| "{}".to_string());
|
||||
format!(
|
||||
"{instructions}\n\nOutput format requirements:\n- Reply with a single JSON value that strictly matches the following JSON Schema.\n- Do not include any commentary, markdown, or extra text.\n- Do not include trailing explanations.\n\nSchema:\n{schema_json}\n",
|
||||
instructions = def.instructions,
|
||||
schema_json = schema_json
|
||||
)
|
||||
} else {
|
||||
def.instructions.clone()
|
||||
};
|
||||
let schema_json =
|
||||
serde_json::to_string_pretty(def.output_schema()).unwrap_or_else(|_| "{}".to_string());
|
||||
let child_instructions = format!(
|
||||
"{}\n\nOutput format requirements:\n- Reply with a single JSON value that strictly matches the following JSON Schema.\n- Do not include any commentary, markdown, or extra text.\n- Do not include trailing explanations.\n\nSchema:\n{}\n",
|
||||
def.instructions, schema_json
|
||||
);
|
||||
|
||||
match def.source {
|
||||
SubagentSource::User | SubagentSource::Project => match parent_base_instructions {
|
||||
|
||||
Reference in New Issue
Block a user