mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-09-01 17:19:24 +00:00
feat: group chat privacy, channel-aware prompts, and safety hardening (#285)
Prevent personal memory (MEMORY.md) from leaking into group chat contexts by adding system_prompt_for_context(is_group_chat) to the workspace. Add channel-specific formatting hints (Discord, Telegram, Slack, WhatsApp), runtime metadata injection, group chat behavioral guidance with NO_REPLY silent token, safety rules in the system prompt, tool call style guidance, wrap_external_content() for untrusted data, and improved workspace seed files with richer identity/soul/agent templates and heartbeat checklist. Co-authored-by: Claude Opus 4.6 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
3124ab2b7f
commit
48b5323ec9
@@ -682,7 +682,15 @@ impl Agent {
|
||||
|
||||
// Convert SubmissionResult to response string
|
||||
match result? {
|
||||
SubmissionResult::Response { content } => Ok(Some(content)),
|
||||
SubmissionResult::Response { content } => {
|
||||
// Suppress silent replies (e.g. from group chat "nothing to say" responses)
|
||||
if crate::llm::is_silent_reply(&content) {
|
||||
tracing::debug!("Suppressing silent reply token");
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(content))
|
||||
}
|
||||
}
|
||||
SubmissionResult::Ok { message } => Ok(message),
|
||||
SubmissionResult::Error { message } => Ok(Some(format!("Error: {}", message))),
|
||||
SubmissionResult::Interrupted => Ok(Some("Interrupted.".into())),
|
||||
|
||||
+13
-2
@@ -40,9 +40,17 @@ impl Agent {
|
||||
thread_id: Uuid,
|
||||
initial_messages: Vec<ChatMessage>,
|
||||
) -> Result<AgenticLoopResult, Error> {
|
||||
// Detect group chat from channel metadata (needed before loading system prompt)
|
||||
let is_group_chat = message
|
||||
.metadata
|
||||
.get("chat_type")
|
||||
.and_then(|v| v.as_str())
|
||||
.is_some_and(|t| t == "group" || t == "channel" || t == "supergroup");
|
||||
|
||||
// Load workspace system prompt (identity files: AGENTS.md, SOUL.md, etc.)
|
||||
// In group chats, MEMORY.md is excluded to prevent leaking personal context.
|
||||
let system_prompt = if let Some(ws) = self.workspace() {
|
||||
match ws.system_prompt().await {
|
||||
match ws.system_prompt_for_context(is_group_chat).await {
|
||||
Ok(prompt) if !prompt.is_empty() => Some(prompt),
|
||||
Ok(_) => None,
|
||||
Err(e) => {
|
||||
@@ -94,7 +102,10 @@ impl Agent {
|
||||
None
|
||||
};
|
||||
|
||||
let mut reasoning = Reasoning::new(self.llm().clone(), self.safety().clone());
|
||||
let mut reasoning = Reasoning::new(self.llm().clone(), self.safety().clone())
|
||||
.with_channel(message.channel.clone())
|
||||
.with_model_name(self.llm().active_model_name())
|
||||
.with_group_chat(is_group_chat);
|
||||
if let Some(prompt) = system_prompt {
|
||||
reasoning = reasoning.with_system_prompt(prompt);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user