Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions crates/buzz-acp/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
#![deny(unsafe_code)]
#![warn(missing_docs)]
//! ACP (Agent Communication Protocol) harness that bridges Buzz relay events
//! to AI agent subprocesses.
//!
//! The harness subscribes to a Buzz relay, routes incoming messages (mentions,
//! reminders, workflow approvals) to managed agent processes via ACP, and
//! publishes their responses back to the relay. It manages the full agent
//! lifecycle: process pooling, turn queuing per channel, rate limiting,
//! observer telemetry, and usage tracking.

mod acp;
mod config;
Expand Down Expand Up @@ -1228,6 +1237,12 @@ impl Drop for RespawnGuard {
// sync entry point — `std::env::set_var` is only safe before tokio spawns
// worker threads (Rust 2024 edition safety requirement).

/// Entry point for the ACP harness binary.
///
/// Propagates legacy environment variables synchronously (before the tokio
/// runtime starts), then hands off to the async main loop which connects to
/// the relay, subscribes to agent-relevant events, and manages agent
/// subprocesses.
pub fn run() -> Result<()> {
config::propagate_legacy_env_vars();
tokio_main()
Expand Down
29 changes: 29 additions & 0 deletions crates/buzz-cli/src/agent_management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,44 @@ const REQUEST_KIND: &str = "agent_management_request";
const MAX_NAME_CHARS: usize = 120;
const MAX_PROMPT_CHARS: usize = 20_000;

/// Owner-reviewed request to create a new personal agent.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateAgentDraft {
/// UUID of the channel the agent will be added to.
pub channel_id: String,
/// Proposed display name for the agent.
pub display_name: String,
/// Proposed system prompt / instructions for the agent.
pub system_prompt: String,
}

/// Owner-reviewed request to update an existing personal agent.
///
/// At least one optional field must be set; an all-`None` request is rejected.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateAgentDraft {
/// UUID of the channel the agent belongs to.
pub channel_id: String,
/// Current name of the personal agent to update.
pub agent_name: String,
/// New display name, if changing it.
#[serde(skip_serializing_if = "Option::is_none")]
pub display_name: Option<String>,
/// Replacement system prompt, if changing it.
#[serde(skip_serializing_if = "Option::is_none")]
pub system_prompt: Option<String>,
/// New runtime identifier, if changing it.
#[serde(skip_serializing_if = "Option::is_none")]
pub runtime: Option<String>,
/// New model provider identifier, if changing it.
#[serde(skip_serializing_if = "Option::is_none")]
pub provider: Option<String>,
/// New model identifier, if changing it.
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
/// Who the agent may respond to (`owner-only` or `anyone`), if changing it.
#[serde(skip_serializing_if = "Option::is_none")]
pub respond_to: Option<String>,
}
Expand Down Expand Up @@ -60,10 +75,15 @@ struct ObserverEvent<T> {
payload: ManagementRequest<T>,
}

/// A signed agent-management observer frame ready to publish, plus the
/// identifiers needed to correlate the relay response with the request.
#[derive(Debug)]
pub struct BuiltDraftRequest {
/// The signed Nostr observer frame event carrying the encrypted request.
pub event: Event,
/// UUID of this draft request, for correlating the owner's response.
pub request_id: String,
/// The request action: `create` or `update`.
pub action: &'static str,
}

Expand Down Expand Up @@ -125,6 +145,10 @@ fn build<T: Serialize>(
})
}

/// Build and sign an owner-reviewed agent-creation draft request.
///
/// Validates the channel UUID, display name, and system prompt length, then
/// encrypts the request to the owner and wraps it in a signed observer frame.
pub fn build_create(
keys: &Keys,
owner: &PublicKey,
Expand All @@ -141,6 +165,11 @@ pub fn build_create(
build(keys, owner, channel_id, "create", request)
}

/// Build and sign an owner-reviewed agent-update draft request.
///
/// Validates the channel UUID and each supplied field, requires at least one
/// field to change, then encrypts the request to the owner and wraps it in a
/// signed observer frame.
pub fn build_update(
keys: &Keys,
owner: &PublicKey,
Expand Down
Loading