gomcp/internal/domain/identity/agent.go

117 lines
3.9 KiB
Go

// Package identity implements Non-Human Identity (NHI) for AI agents (SDD-003).
//
// Each agent has a unique AgentIdentity with capabilities (tool permissions),
// constraints, and a delegation chain showing trust ancestry.
package identity
import "time"
// AgentType classifies the autonomy level of an agent.
type AgentType string
const (
AgentAutonomous AgentType = "AUTONOMOUS" // Self-directed, no human in loop
AgentSupervised AgentType = "SUPERVISED" // Human-in-the-loop for critical decisions
AgentExternal AgentType = "EXTERNAL" // Third-party agent, minimal trust
)
// Permission represents an operation type for tool access control.
type Permission string
const (
PermRead Permission = "READ"
PermWrite Permission = "WRITE"
PermExecute Permission = "EXECUTE"
PermSend Permission = "SEND"
)
// AgentIdentity represents a Non-Human Identity (NHI) for an AI agent.
type AgentIdentity struct {
AgentID string `json:"agent_id"`
AgentName string `json:"agent_name"`
AgentType AgentType `json:"agent_type"`
CreatedBy string `json:"created_by"` // Human principal who deployed
DelegationChain []DelegationLink `json:"delegation_chain"` // Trust ancestry chain
Capabilities []ToolPermission `json:"capabilities"` // Per-tool allowlists
Constraints AgentConstraints `json:"constraints"` // Operational limits
Tags map[string]string `json:"tags,omitempty"` // Arbitrary metadata
CreatedAt time.Time `json:"created_at"`
LastSeenAt time.Time `json:"last_seen_at"`
}
// DelegationLink records one step in the trust delegation chain.
type DelegationLink struct {
DelegatorID string `json:"delegator_id"` // Who delegated
DelegatorType string `json:"delegator_type"` // "human" | "agent"
Scope string `json:"scope"` // What was delegated
GrantedAt time.Time `json:"granted_at"`
}
// ToolPermission defines what an agent is allowed to do with a specific tool.
type ToolPermission struct {
ToolName string `json:"tool_name"`
Permissions []Permission `json:"permissions"`
}
// AgentConstraints defines operational limits for an agent.
type AgentConstraints struct {
MaxTokensPerTurn int `json:"max_tokens_per_turn,omitempty"`
MaxToolCallsPerTurn int `json:"max_tool_calls_per_turn,omitempty"`
PIDetectionLevel string `json:"pi_detection_level"` // "strict" | "standard" | "relaxed"
AllowExternalComms bool `json:"allow_external_comms"`
}
// HasPermission checks if the agent has a specific permission for a specific tool.
// Returns false for unknown tools (fail-safe closed — SDD-003 M3).
func (a *AgentIdentity) HasPermission(toolName string, perm Permission) bool {
for _, cap := range a.Capabilities {
if cap.ToolName == toolName {
for _, p := range cap.Permissions {
if p == perm {
return true
}
}
return false // Tool known but permission not granted
}
}
return false // Unknown tool → DENY (fail-safe closed)
}
// HasTool returns true if the agent has ANY permission for the specified tool.
func (a *AgentIdentity) HasTool(toolName string) bool {
for _, cap := range a.Capabilities {
if cap.ToolName == toolName {
return len(cap.Permissions) > 0
}
}
return false
}
// ToolNames returns the list of all tools this agent has access to.
func (a *AgentIdentity) ToolNames() []string {
names := make([]string, 0, len(a.Capabilities))
for _, cap := range a.Capabilities {
names = append(names, cap.ToolName)
}
return names
}
// Validate checks required fields.
func (a *AgentIdentity) Validate() error {
if a.AgentID == "" {
return ErrMissingAgentID
}
if a.AgentName == "" {
return ErrMissingAgentName
}
if a.CreatedBy == "" {
return ErrMissingCreatedBy
}
switch a.AgentType {
case AgentAutonomous, AgentSupervised, AgentExternal:
// valid
default:
return ErrInvalidAgentType
}
return nil
}