Agents & Entities
Entities represent identities within Stoneforge - AI agents, humans, or system processes. They are the actors that create, modify, and interact with all other elements.
Entity Interface
interface Entity extends Element {
readonly type : 'entity' ;
// Identity
readonly name : string ; // System-wide unique identifier
readonly entityType : EntityTypeValue ;
// Cryptographic Identity (optional)
readonly publicKey ?: string ; // Ed25519 public key, base64 encoded
// Organizational Hierarchy (optional)
readonly reportsTo ?: EntityId ;
}
System-wide unique identifier name (1-100 characters, must start with letter)
Classification: agent, human, or system
Ed25519 public key, base64 encoded (44 characters) for cryptographic identity
Manager entity reference for organizational hierarchy
Entity Types
const EntityTypeValue = {
AGENT: 'agent' , // AI agent - automated actors performing work
HUMAN: 'human' , // Human user - manual actors in the system
SYSTEM: 'system' , // System process - automated infrastructure
} as const ;
type EntityTypeValue = 'agent' | 'human' | 'system' ;
AI agents are automated actors that perform work:
Execute tasks autonomously
Spawn worker processes
Make decisions based on prompts
Examples: Director, Worker, Steward
Human users are manual actors:
Create and manage tasks
Review agent work
Approve changes
Collaborate with agents and other humans
System processes are automated infrastructure:
Background jobs
Scheduled tasks
Integration services
System-level operations
Entity Names
Entity names must be unique system-wide and follow strict validation rules.
Name Validation Rules
Name pattern: ^[a-zA-Z][a-zA-Z0-9_-]*$
Must start with a letter
Followed by alphanumeric, hyphen, or underscore
No whitespace
Reserved Names
const RESERVED_NAMES = [ 'system' , 'anonymous' , 'unknown' ] as const ;
Reserved names cannot be used for entity creation.
Name Validation
// Validate entity name format
validateEntityName ( value : unknown ): string
// Type guard
isValidEntityName ( value : unknown ): value is string
// Check if name is reserved
isReservedName ( name : string ): name is ReservedName
Creating Entities
interface CreateEntityInput {
name : string ;
entityType : EntityTypeValue ;
createdBy : EntityId ;
// Optional fields
publicKey ?: string ; // Ed25519 public key, base64 encoded
reportsTo ?: EntityId ;
tags ?: string [];
metadata ?: Record < string , unknown >;
}
// Create a new entity
await createEntity ( input : CreateEntityInput , config ?: IdGeneratorConfig ): Promise < Entity >
Show Example: Create AI Agent
import { createEntity , asEntityId } from '@stoneforge/core' ;
const agent = await createEntity ({
name: 'worker-alpha' ,
entityType: 'agent' ,
createdBy: asEntityId ( 'el-system' ),
metadata: {
role: 'worker' ,
capabilities: [ 'typescript' , 'testing' ],
},
tags: [ 'ai' , 'worker' ],
});
Cryptographic Identity
Entities can have optional cryptographic identity via Ed25519 public keys.
Ed25519 public keys are 32 bytes
Encoded as base64 (44 characters with padding)
Pattern: ^[A-Za-z0-9+/]{43}=$
Public Key Validation
// Validate public key format
validatePublicKey ( value : unknown ): string
// Type guard
isValidPublicKey ( value : unknown ): value is string
// Check if entity has cryptographic identity
hasCryptographicIdentity ( entity : Entity ): boolean
Key Rotation
Rotate an entity’s public key with cryptographic verification:
interface KeyRotationInput {
newPublicKey : string ;
signature : string ; // Signed with CURRENT private key
signedAt : string ; // ISO 8601 timestamp
}
interface KeyRotationOptions {
maxSignatureAge ?: number ; // default: 5 minutes
skipTimestampValidation ?: boolean ;
}
// Rotate entity key
await rotateEntityKey (
entity : Entity ,
input : KeyRotationInput ,
verifySignature : ( message : string , signature : string , publicKey : string ) => Promise < boolean > ,
options ?: KeyRotationOptions
): Promise < KeyRotationResult >
Show Example: Prepare Key Rotation
import { prepareKeyRotation , constructKeyRotationMessage } from '@stoneforge/core' ;
// Prepare rotation request
const { message , timestamp } = prepareKeyRotation ( entity , newPublicKey );
// Message format: "rotate-key:{entityId}:{newPublicKey}:{timestamp}"
// Sign this message with the CURRENT private key
const signature = await signWithPrivateKey ( message , currentPrivateKey );
// Submit rotation
const result = await rotateEntityKey ( entity , {
newPublicKey ,
signature ,
signedAt: timestamp ,
}, verifySignatureFunction );
Key Revocation
Revoke an entity’s public key (converts to soft identity):
interface KeyRevocationInput {
reason ?: string ;
signature : string ; // Signed with CURRENT private key
signedAt : string ; // ISO 8601 timestamp
}
// Revoke entity key
await revokeEntityKey (
entity : Entity ,
input : KeyRevocationInput ,
verifySignature : ( message : string , signature : string , publicKey : string ) => Promise < boolean > ,
options ?: KeyRevocationOptions
): Promise < KeyRevocationResult >
Entity Activation
Entities can be deactivated while preserving historical references.
Deactivation
interface DeactivateEntityInput {
reason ?: string ;
deactivatedBy : EntityId ;
}
// Deactivate entity
deactivateEntity ( entity : Entity , input : DeactivateEntityInput ): Entity
Deactivated entities:
Have metadata.active = false
Preserved for historical references
Should be filtered from active listings
Reactivation
// Reactivate entity
reactivateEntity ( entity : Entity , reactivatedBy : EntityId ): Entity
Status Checks
// Check if entity is active
isEntityActive ( entity : Entity ): boolean
// Check if entity is deactivated
isEntityDeactivated ( entity : Entity ): boolean
// Get deactivation details
getDeactivationDetails ( entity : Entity ): {
deactivatedAt? : string ;
deactivatedBy ?: string ;
reason ?: string ;
} | null
Updating Entities
interface UpdateEntityInput {
publicKey ?: string ;
reportsTo ?: EntityId | null ; // null to clear
tags ?: string [];
metadata ?: Record < string , unknown >;
}
// Update entity (name and entityType are immutable)
updateEntity ( entity : Entity , input : UpdateEntityInput ): Entity
Entity name and entityType are immutable after creation.
Filtering and Searching
Filter Functions
// Filter by entity type
filterByEntityType < T extends Entity >( entities : T [], entityType : EntityTypeValue ) : T []
// Filter by creator
filterByCreator < T extends Entity >( entities : T [], createdBy : EntityId ) : T []
// Filter with/without public key
filterWithPublicKey < T extends Entity >( entities : T []) : T []
filterWithoutPublicKey < T extends Entity >( entities : T []) : T []
// Filter by tag
filterByTag < T extends Entity >( entities : T [], tag : string ) : T []
filterByAnyTag < T extends Entity >( entities : T [], tags : string []) : T []
filterByAllTags < T extends Entity >( entities : T [], tags : string []) : T []
// Filter by activation status
filterActiveEntities < T extends Entity >( entities : T []) : T []
filterDeactivatedEntities < T extends Entity >( entities : T []) : T []
// Filter by key revocation status
filterRevokedKeyEntities < T extends Entity >( entities : T []) : T []
filterNonRevokedKeyEntities < T extends Entity >( entities : T []) : T []
Search Functions
// Search by name (case-insensitive substring)
searchByName < T extends Entity >( entities : T [], query : string ) : T []
// Find by exact name
findByName < T extends Entity >( entities : T [], name : string ) : T | undefined
// Find by ID
findById < T extends Entity >( entities : T [], id : EntityId | string ) : T | undefined
// Check name uniqueness
isNameUnique ( entities : Entity [], name : string , excludeId ?: EntityId | string ) : boolean
Sort Functions
// Sort by name alphabetically
sortByName < T extends Entity >( entities : T [], ascending ?: boolean ) : T []
// Sort by creation date
sortByCreationDate < T extends Entity >( entities : T [], ascending ?: boolean ) : T []
// Sort by update date
sortByUpdateDate < T extends Entity >( entities : T [], ascending ?: boolean ) : T []
// Sort by entity type
sortByEntityType < T extends Entity >( entities : T []) : T []
Assignment Utilities
Query items (tasks, etc.) by entity relationships:
// Get items assigned to entity
getAssignedTo < T extends Assignable >( items : T [], entityId : string ) : T []
// Get items created by entity
getCreatedBy < T extends Assignable >( items : T [], entityId : string ) : T []
// Get items where entity is assignee or creator
getRelatedTo < T extends Assignable >( items : T [], entityId : string ) : T []
// Count assignments by entity
countAssignmentsByEntity < T extends Assignable >( items : T []) : Map < string , number >
// Get top assignees
getTopAssignees < T extends Assignable >( items : T [], limit ?: number ) : Array <[ string , number ]>
// Get assignment stats for entity
getEntityAssignmentStats < T extends Assignable >( items : T [], entityId : string ) : {
assignedCount : number ;
createdCount : number ;
totalRelated : number ;
}
Team Membership
Query entity team relationships:
// Get teams entity belongs to
getEntityTeamMemberships < T extends TeamLike >( teams : T [], entityId : string ) : T []
// Count team memberships
countEntityTeamMemberships ( teams : TeamLike [], entityId : string ) : number
// Check if entity is in any team
isEntityInAnyTeam ( teams : TeamLike [], entityId : string ) : boolean
// Check if entity is in specific team
isEntityInTeam ( team : TeamLike , entityId : string ) : boolean
// Get teammates (entities sharing teams)
getTeammates < T extends TeamLike >( teams : T [], entityId : string ) : string []
// Get team membership stats
getEntityTeamMembershipStats < T extends TeamLike >( teams : T [], entityId : string ) : {
teamCount : number ;
teammateCount : number ;
teamIds : string [];
teamNames : string [];
}
Utility Functions
// Get display name from metadata or fall back to name
getEntityDisplayName ( entity : Entity ): string
// Check if two entities have same name
entitiesHaveSameName ( a : Entity , b : Entity ): boolean
// Get unique tags from entities
getUniqueTags ( entities : Entity []): string []
// Count entities by type
countByEntityType ( entities : Entity []): Record < EntityTypeValue , number >
Type Guards
// Check if value is a valid Entity
isEntity ( value : unknown ): value is Entity
// Comprehensive validation with detailed errors
validateEntity ( value : unknown ): Entity
// Validate entity type
validateEntityType ( value : unknown ): EntityTypeValue
Best Practices
Unique Names Ensure entity names are unique system-wide using isNameUnique()
Soft Identity vs. Cryptographic Use public keys for trusted operations, soft identity for general use
Deactivate, Don't Delete Deactivate entities instead of deleting to preserve historical references
Hierarchical Organization Use reportsTo to build organizational hierarchies for agents and humans