diff --git a/docs/protocol/draft/schema.mdx b/docs/protocol/draft/schema.mdx index 76f259a72..85da8dec9 100644 --- a/docs/protocol/draft/schema.mdx +++ b/docs/protocol/draft/schema.mdx @@ -1217,6 +1217,20 @@ additional roots are activated for the new session. McpServer[]} required> List of MCP (Model Context Protocol) servers the agent should connect to. + + Optional system-level instructions the client provides for this session. + +When present, the agent MUST incorporate this content into its system prompt +construction alongside its own built-in instructions. It MUST NOT discard its own +safety guardrails, identity, or internal configuration in favor of client-provided +content — the semantics are additive, not a replacement. Agents MUST have their own +default behavior and MUST NOT require a client system prompt to function. If the agent +cannot incorporate the system prompt, it MUST return a JSON-RPC error and MUST NOT +create the session. + +When omitted, the agent uses its own default system prompt unchanged. + + #### NewSessionResponse diff --git a/docs/protocol/draft/session-setup.mdx b/docs/protocol/draft/session-setup.mdx index e8e3ac514..983686f76 100644 --- a/docs/protocol/draft/session-setup.mdx +++ b/docs/protocol/draft/session-setup.mdx @@ -48,6 +48,7 @@ Clients create a new session by calling the `session/new` method with: - The [working directory](#working-directory) for the session - A list of [MCP servers](#mcp-servers) the Agent should connect to +- An optional **system prompt** providing client-supplied instructions for the session ```json { @@ -56,6 +57,7 @@ Clients create a new session by calling the `session/new` method with: "method": "session/new", "params": { "cwd": "/home/user/project", + "systemPrompt": "You are a concise code-review assistant.", "mcpServers": [ { "name": "filesystem", diff --git a/docs/protocol/schema.mdx b/docs/protocol/schema.mdx index 79b6693ec..8eb462838 100644 --- a/docs/protocol/schema.mdx +++ b/docs/protocol/schema.mdx @@ -366,6 +366,20 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/exte McpServer[]} required> List of MCP (Model Context Protocol) servers the agent should connect to. + + Optional system-level instructions the client provides for this session. + +When present, the agent MUST incorporate this content into its system prompt +construction alongside its own built-in instructions. It MUST NOT discard its own +safety guardrails, identity, or internal configuration in favor of client-provided +content — the semantics are additive, not a replacement. Agents MUST have their own +default behavior and MUST NOT require a client system prompt to function. If the agent +cannot incorporate the system prompt, it MUST return a JSON-RPC error and MUST NOT +create the session. + +When omitted, the agent uses its own default system prompt unchanged. + + #### NewSessionResponse diff --git a/docs/protocol/session-setup.mdx b/docs/protocol/session-setup.mdx index f323f3205..457dcc8c9 100644 --- a/docs/protocol/session-setup.mdx +++ b/docs/protocol/session-setup.mdx @@ -43,6 +43,7 @@ Clients create a new session by calling the `session/new` method with: - The [working directory](#working-directory) for the session - A list of [MCP servers](#mcp-servers) the Agent should connect to +- An optional **system prompt** providing client-supplied instructions for the session ```json { @@ -51,6 +52,7 @@ Clients create a new session by calling the `session/new` method with: "method": "session/new", "params": { "cwd": "/home/user/project", + "systemPrompt": "You are a concise code-review assistant.", "mcpServers": [ { "name": "filesystem", diff --git a/schema/schema.json b/schema/schema.json index 9aca01f4e..92502c9d8 100644 --- a/schema/schema.json +++ b/schema/schema.json @@ -1751,6 +1751,10 @@ "$ref": "#/$defs/McpServer" }, "type": "array" + }, + "systemPrompt": { + "description": "Optional system-level instructions the client provides for this session.\n\nWhen present, the agent MUST incorporate this content into its system prompt\nconstruction alongside its own built-in instructions. It MUST NOT discard its own\nsafety guardrails, identity, or internal configuration in favor of client-provided\ncontent — the semantics are additive, not a replacement. Agents MUST have their own\ndefault behavior and MUST NOT require a client system prompt to function. If the agent\ncannot incorporate the system prompt, it MUST return a JSON-RPC error and MUST NOT\ncreate the session.\n\nWhen omitted, the agent uses its own default system prompt unchanged.", + "type": ["string", "null"] } }, "required": ["cwd", "mcpServers"], diff --git a/schema/schema.unstable.json b/schema/schema.unstable.json index abb6fb8a9..e29c704f9 100644 --- a/schema/schema.unstable.json +++ b/schema/schema.unstable.json @@ -4462,6 +4462,10 @@ "$ref": "#/$defs/McpServer" }, "type": "array" + }, + "systemPrompt": { + "description": "Optional system-level instructions the client provides for this session.\n\nWhen present, the agent MUST incorporate this content into its system prompt\nconstruction alongside its own built-in instructions. It MUST NOT discard its own\nsafety guardrails, identity, or internal configuration in favor of client-provided\ncontent — the semantics are additive, not a replacement. Agents MUST have their own\ndefault behavior and MUST NOT require a client system prompt to function. If the agent\ncannot incorporate the system prompt, it MUST return a JSON-RPC error and MUST NOT\ncreate the session.\n\nWhen omitted, the agent uses its own default system prompt unchanged.", + "type": ["string", "null"] } }, "required": ["cwd", "mcpServers"], diff --git a/src/agent.rs b/src/agent.rs index 9caf07440..1babfb129 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -942,6 +942,18 @@ pub struct NewSessionRequest { pub additional_directories: Vec, /// List of MCP (Model Context Protocol) servers the agent should connect to. pub mcp_servers: Vec, + /// Optional system-level instructions the client provides for this session. + /// + /// When present, the agent MUST incorporate this content into its system prompt + /// construction alongside its own built-in instructions. It MUST NOT discard its own + /// safety guardrails, identity, or internal configuration in favor of client-provided + /// content — the semantics are additive, not a replacement. Agents MUST have their own + /// default behavior and MUST NOT require a client system prompt to function. If the agent + /// cannot incorporate the system prompt, it MUST return a JSON-RPC error and MUST NOT + /// create the session. + /// + /// When omitted, the agent uses its own default system prompt unchanged. + pub system_prompt: Option, /// The _meta property is reserved by ACP to allow clients and agents to attach additional /// metadata to their interactions. Implementations MUST NOT make assumptions about values at /// these keys. @@ -959,6 +971,7 @@ impl NewSessionRequest { #[cfg(feature = "unstable_session_additional_directories")] additional_directories: vec![], mcp_servers: vec![], + system_prompt: None, meta: None, } } @@ -982,6 +995,16 @@ impl NewSessionRequest { self } + /// Optional system-level instructions the client provides for this session. + /// + /// When present, the agent incorporates this content into its system prompt alongside + /// its own built-in instructions (additive, not a replacement). + #[must_use] + pub fn system_prompt(mut self, system_prompt: impl Into) -> Self { + self.system_prompt = Some(system_prompt.into()); + self + } + /// The _meta property is reserved by ACP to allow clients and agents to attach additional /// metadata to their interactions. Implementations MUST NOT make assumptions about values at /// these keys. @@ -6156,4 +6179,36 @@ mod test_serialization { let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap(); assert!(deserialized.providers.is_some()); } + + #[test] + fn test_new_session_request_system_prompt_round_trip() { + let request = NewSessionRequest::new("/home/user/project") + .system_prompt("You are a code review specialist."); + + let json = serde_json::to_value(&request).unwrap(); + assert_eq!( + json["systemPrompt"], + json!("You are a code review specialist.") + ); + + let deserialized: NewSessionRequest = serde_json::from_value(json).unwrap(); + assert_eq!( + deserialized.system_prompt.as_deref(), + Some("You are a code review specialist.") + ); + } + + #[test] + fn test_new_session_request_system_prompt_absent_is_omitted() { + let request = NewSessionRequest::new("/home/user/project"); + + let json = serde_json::to_value(&request).unwrap(); + assert!( + json.get("systemPrompt").is_none(), + "skip_serializing_none should omit systemPrompt when absent" + ); + + let deserialized: NewSessionRequest = serde_json::from_value(json).unwrap(); + assert!(deserialized.system_prompt.is_none()); + } }