This commit introduces a multi-agent Swarm Engine to PicoClaw, enabling complex task orchestration through autonomous collaboration and long-term semantic memory. Key Features: - Actor Model Architecture: Every agent (node) runs in an isolated goroutine, communicating via a lightweight internal Event Bus. - Hierarchical Delegation: Manager nodes can dynamically spawn specialized worker nodes (Researchers, Analysts, etc.) to perform sub-tasks in parallel. - Hybrid Memory System: Combined SQLite for state persistence and Chromem-go for a persistent, cross-swarm Vector Knowledge Base. - Progressive Summarization: Implemented an intelligent memory pruning mechanism that summarizes older context before truncation to preserve findings without exceeding token limits. - Role-Based Access Control (RBAC): Configurable tool policies per role (e.g., Researchers can browse but not execute shell commands). Performance & Scaling: - Low Footprint: Idle memory usage is ~7-8 MB RSS. - Efficient Scaling: During a stress test with 10 concurrent agents performing intensive research, memory usage peaked at only 27 MB. - Per-Node Cost: Each active agent consumes approximately 0.6 MB to 2 MB of physical RAM depending on conversation length and summarization state. - Stability: Successfully handled 10 parallel LLM requests with zero race conditions, showcasing the robustness of the Go-based Actor model. Integration: - Native CLI Support: Added /swarm spawn, /swarm list, and /swarm status commands. - Mermaid Visualization: Support for /swarm viz <id> to generate organizational charts of active agent hierarchies. - Configurable: Roles, models, and security policies are fully customizable via config.json.
51 lines
No EOL
1.1 KiB
Go
51 lines
No EOL
1.1 KiB
Go
package core
|
|
|
|
import "strings"
|
|
|
|
// RolePolicy defines permissions for a role
|
|
type RolePolicy struct {
|
|
AllowedTools []string // Whitelist (if empty, nothing allowed unless wildcard)
|
|
DeniedTools []string // Blacklist (overrides whitelist)
|
|
}
|
|
|
|
type PolicyChecker struct {
|
|
policies map[string]RolePolicy
|
|
}
|
|
|
|
func NewPolicyChecker(policies map[string]RolePolicy) *PolicyChecker {
|
|
return &PolicyChecker{
|
|
policies: policies,
|
|
}
|
|
}
|
|
|
|
// CanUseTool checks if a role is allowed to use a specific tool
|
|
func (pc *PolicyChecker) CanUseTool(roleName, toolName string) bool {
|
|
policy, ok := pc.policies[roleName]
|
|
if !ok {
|
|
// Default restrictive policy for unknown roles
|
|
return false
|
|
}
|
|
|
|
// 1. Check Denied List first (Safety First)
|
|
for _, denied := range policy.DeniedTools {
|
|
if matchWildcard(denied, toolName) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
// 2. Check Allowed List
|
|
for _, allowed := range policy.AllowedTools {
|
|
if matchWildcard(allowed, toolName) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func matchWildcard(pattern, subject string) bool {
|
|
if pattern == "*" {
|
|
return true
|
|
}
|
|
return strings.EqualFold(pattern, subject)
|
|
} |