HR¶
Agent lifecycle management: hiring, firing, onboarding, offboarding, performance tracking, and promotion/demotion.
Models¶
models
¶
HR domain models.
Frozen Pydantic models for hiring, firing, onboarding, offboarding, and agent lifecycle events.
CandidateCard
pydantic-model
¶
Bases: BaseModel
Generated candidate for a hiring request.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique candidate identifier. |
name |
NotBlankStr
|
Proposed agent name. |
role |
NotBlankStr
|
Proposed role. |
department |
NotBlankStr
|
Target department. |
level |
SeniorityLevel
|
Proposed seniority level. |
skills |
tuple[Skill, ...]
|
Agent skills. |
rationale |
NotBlankStr
|
Why this candidate was generated. |
estimated_monthly_cost |
float
|
Estimated monthly cost in the configured currency. |
template_source |
NotBlankStr | None
|
Template used for generation, if any. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
name(NotBlankStr) -
role(NotBlankStr) -
department(NotBlankStr) -
level(SeniorityLevel) -
skills(tuple[Skill, ...]) -
rationale(NotBlankStr) -
estimated_monthly_cost(float) -
template_source(NotBlankStr | None)
estimated_monthly_cost
pydantic-field
¶
Estimated monthly cost in the configured currency
HiringRequest
pydantic-model
¶
Bases: BaseModel
Request to hire a new agent.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique request identifier. |
requested_by |
NotBlankStr
|
Agent or human who initiated the request. |
department |
NotBlankStr
|
Target department. |
role |
NotBlankStr
|
Desired role. |
level |
SeniorityLevel
|
Desired seniority level. |
required_skills |
tuple[NotBlankStr, ...]
|
Skills the candidate must have. |
reason |
NotBlankStr
|
Business justification. |
budget_limit_monthly |
float | None
|
Maximum monthly cost in the configured currency, if constrained. |
template_name |
NotBlankStr | None
|
Template to use for candidate generation. |
status |
HiringRequestStatus
|
Current request status. |
created_at |
AwareDatetime
|
When the request was created. |
candidates |
tuple[CandidateCard, ...]
|
Generated candidate cards. |
selected_candidate_id |
NotBlankStr | None
|
ID of the chosen candidate. |
approval_id |
NotBlankStr | None
|
ID of the associated approval item. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
requested_by(NotBlankStr) -
department(NotBlankStr) -
role(NotBlankStr) -
level(SeniorityLevel) -
required_skills(tuple[NotBlankStr, ...]) -
reason(NotBlankStr) -
budget_limit_monthly(float | None) -
template_name(NotBlankStr | None) -
status(HiringRequestStatus) -
created_at(AwareDatetime) -
candidates(tuple[CandidateCard, ...]) -
selected_candidate_id(NotBlankStr | None) -
approval_id(NotBlankStr | None)
Validators:
-
_validate_status_candidate_consistency
budget_limit_monthly
pydantic-field
¶
Maximum monthly cost in the configured currency, if constrained
FiringRequest
pydantic-model
¶
Bases: BaseModel
Request to terminate an agent.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique request identifier. |
agent_id |
NotBlankStr
|
Agent to be terminated. |
agent_name |
NotBlankStr
|
Agent's display name. |
reason |
FiringReason
|
Reason for termination. |
requested_by |
NotBlankStr
|
Initiator of the firing. |
details |
str
|
Additional context. |
created_at |
AwareDatetime
|
When the request was created. |
completed_at |
AwareDatetime | None
|
When the firing was completed. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
agent_id(NotBlankStr) -
agent_name(NotBlankStr) -
reason(FiringReason) -
requested_by(NotBlankStr) -
details(str) -
created_at(AwareDatetime) -
completed_at(AwareDatetime | None)
Validators:
-
_validate_temporal_order
OnboardingStepRecord
pydantic-model
¶
Bases: BaseModel
Record of a single onboarding step.
Attributes:
| Name | Type | Description |
|---|---|---|
step |
OnboardingStep
|
The onboarding step. |
completed |
bool
|
Whether this step is complete. |
completed_at |
AwareDatetime | None
|
When this step was completed. |
notes |
str
|
Optional notes from the step. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
step(OnboardingStep) -
completed(bool) -
completed_at(AwareDatetime | None) -
notes(str)
Validators:
-
_validate_completed_consistency
OnboardingChecklist
pydantic-model
¶
Bases: BaseModel
Agent onboarding checklist tracking all steps.
Attributes:
| Name | Type | Description |
|---|---|---|
agent_id |
NotBlankStr
|
Agent being onboarded. |
steps |
tuple[OnboardingStepRecord, ...]
|
Individual step records. |
started_at |
AwareDatetime
|
When onboarding began. |
completed_at |
AwareDatetime | None
|
When all steps were completed. |
is_complete |
bool
|
Whether all steps are done (computed). |
Config:
frozen:Trueallow_inf_nan:False
Fields:
-
agent_id(NotBlankStr) -
steps(tuple[OnboardingStepRecord, ...]) -
started_at(AwareDatetime) -
completed_at(AwareDatetime | None)
Validators:
-
_validate_completion_consistency
OffboardingRecord
pydantic-model
¶
Bases: BaseModel
Record of a completed offboarding process.
Attributes:
| Name | Type | Description |
|---|---|---|
agent_id |
NotBlankStr
|
Agent who was offboarded. |
agent_name |
NotBlankStr
|
Agent's display name. |
firing_request_id |
NotBlankStr
|
Associated firing request. |
tasks_reassigned |
tuple[NotBlankStr, ...]
|
IDs of reassigned tasks. |
memory_archive_id |
NotBlankStr | None
|
ID of the memory archive, if created. |
org_memories_promoted |
int
|
Number of memories promoted to org. |
team_notification_sent |
bool
|
Whether team was notified. |
started_at |
AwareDatetime
|
When offboarding started. |
completed_at |
AwareDatetime
|
When offboarding finished. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
agent_id(NotBlankStr) -
agent_name(NotBlankStr) -
firing_request_id(NotBlankStr) -
tasks_reassigned(tuple[NotBlankStr, ...]) -
memory_archive_id(NotBlankStr | None) -
org_memories_promoted(int) -
team_notification_sent(bool) -
started_at(AwareDatetime) -
completed_at(AwareDatetime)
Validators:
-
_validate_temporal_order
AgentLifecycleEvent
pydantic-model
¶
Bases: BaseModel
Record of an agent lifecycle event.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique event identifier. |
agent_id |
NotBlankStr
|
Agent the event relates to. |
agent_name |
NotBlankStr
|
Agent's display name. |
event_type |
LifecycleEventType
|
Type of lifecycle event. |
timestamp |
AwareDatetime
|
When the event occurred. |
initiated_by |
NotBlankStr
|
Who triggered the event. |
details |
str
|
Human-readable event details. |
metadata |
dict[str, str]
|
Additional structured metadata. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
agent_id(NotBlankStr) -
agent_name(NotBlankStr) -
event_type(LifecycleEventType) -
timestamp(AwareDatetime) -
initiated_by(NotBlankStr) -
details(str) -
metadata(dict[str, str])
Registry¶
registry
¶
Agent registry service.
Hot-pluggable agent registry for tracking active agents, their identities, and lifecycle status transitions (D8.3).
AgentRegistryService
¶
Hot-pluggable agent registry.
Coroutine-safe via asyncio.Lock within a single event loop. Stores agent identities keyed by agent ID (string form of UUID).
Source code in src/synthorg/hr/registry.py
has_versioning
property
¶
Return True when a versioning service is attached.
Public predicate used by the app factory's startup wiring so it
doesn't need to read the private _versioning slot.
clear
async
¶
Reset all registered agents.
Holds the same self._lock as register / unregister
/ update_* so a concurrent caller cannot observe a partial
clear -- the registry is either fully empty or in the state
the contending writer claimed.
New async test fixtures should call await registry.clear()
directly. The legacy sync entry point used to live on this
class as reset_for_test_sync; it has been moved to
:mod:synthorg.hr.registry_testing so the lock-bypass cannot
be invoked from production code by autocomplete. Sync pytest
fixtures (tests/unit/api/conftest.py) call
reset_registry_for_test_sync(registry) from that module.
Source code in src/synthorg/hr/registry.py
bind_versioning
¶
Attach a versioning service after construction.
Enables the app factory to construct the registry synchronously in
create_app() and wire versioning later in on_startup(), after
the persistence backend is connected (its identity_versions
property requires connect() to have run).
Source code in src/synthorg/hr/registry.py
register
async
¶
Register a new agent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identity
|
AgentIdentity
|
The agent identity to register. |
required |
saved_by
|
str
|
Actor triggering the registration (recorded in
version history). Defaults to |
'system'
|
Raises:
| Type | Description |
|---|---|
AgentAlreadyRegisteredError
|
If the agent is already registered. |
Source code in src/synthorg/hr/registry.py
unregister
async
¶
Remove an agent from the registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
The agent identifier to remove. |
required |
Returns:
| Type | Description |
|---|---|
AgentIdentity
|
The removed agent identity. |
Raises:
| Type | Description |
|---|---|
AgentNotFoundError
|
If the agent is not found. |
Source code in src/synthorg/hr/registry.py
get
async
¶
Retrieve an agent identity by ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
The agent identifier. |
required |
Returns:
| Type | Description |
|---|---|
AgentIdentity | None
|
The agent identity, or None if not found. |
Source code in src/synthorg/hr/registry.py
get_by_name
async
¶
Retrieve an agent identity by name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
NotBlankStr
|
The agent name to search for. |
required |
Returns:
| Type | Description |
|---|---|
AgentIdentity | None
|
The first matching agent, or None. |
Source code in src/synthorg/hr/registry.py
get_by_names
async
¶
Batch lookup preserving input order with None for misses.
Acquires the registry lock exactly once regardless of batch
size. Fanning out N separate get_by_name calls (the old
pattern) required N lock acquisitions and serialised each
lookup under a shared lock; this batch method reduces that to
a single acquisition.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
names
|
tuple[NotBlankStr, ...]
|
Ordered tuple of agent names to resolve (case-insensitive). |
required |
Returns:
| Type | Description |
|---|---|
AgentIdentity | None
|
Tuple of resolved identities in the same order as |
...
|
|
tuple[AgentIdentity | None, ...]
|
|
tuple[AgentIdentity | None, ...]
|
registered agents share the same name (case-insensitive), |
tuple[AgentIdentity | None, ...]
|
the first-registered identity wins, matching |
tuple[AgentIdentity | None, ...]
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/synthorg/hr/registry.py
list_active
async
¶
List all agents with ACTIVE status.
Returns:
| Type | Description |
|---|---|
tuple[AgentIdentity, ...]
|
Tuple of active agent identities. |
Source code in src/synthorg/hr/registry.py
list_by_department
async
¶
List agents in a specific department.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
department
|
NotBlankStr
|
Department name to filter by. |
required |
Returns:
| Type | Description |
|---|---|
tuple[AgentIdentity, ...]
|
Tuple of matching agent identities. |
Source code in src/synthorg/hr/registry.py
update_status
async
¶
Update an agent's lifecycle status.
Emits HR_AGENT_STATUS_TRANSITIONED AFTER the registry
write succeeds, carrying from_status / to_status /
agent_id so observers can audit every persisted hop on
the agent lifecycle. No-op transitions (status unchanged)
skip the transition event but still log
HR_REGISTRY_STATUS_UPDATED for the write itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
The agent identifier. |
required |
status
|
AgentStatus
|
New status. |
required |
Returns:
| Type | Description |
|---|---|
AgentIdentity
|
Updated agent identity. |
Raises:
| Type | Description |
|---|---|
AgentNotFoundError
|
If the agent is not found. |
Source code in src/synthorg/hr/registry.py
update_identity
async
¶
Update agent identity fields via model_copy(update=...).
Only fields in _UPDATABLE_FIELDS are accepted. Use
update_status for status changes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
The agent identifier. |
required |
**updates
|
Any
|
Fields to update on the AgentIdentity. |
{}
|
Returns:
| Type | Description |
|---|---|
AgentIdentity
|
Updated agent identity. |
Raises:
| Type | Description |
|---|---|
AgentNotFoundError
|
If the agent is not found. |
ValueError
|
If any field is not in the allowlist. |
Source code in src/synthorg/hr/registry.py
evolve_identity
async
¶
Apply an evolved identity after evolution guards have passed.
Replaces the agent's identity wholesale. Unlike
update_identity (which restricts to an allowlist), this
method accepts any field changes because the evolution pipeline
has already validated them through guards.
Immutable identifiers (id, name, department) must
match the existing identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
The agent to evolve. |
required |
evolved_identity
|
AgentIdentity
|
The complete new identity. |
required |
evolution_rationale
|
str
|
Human-readable reason (for audit). |
required |
Returns:
| Type | Description |
|---|---|
AgentIdentity
|
The updated agent identity. |
Raises:
| Type | Description |
|---|---|
AgentNotFoundError
|
If agent not found. |
ValueError
|
If immutable fields differ. |
Source code in src/synthorg/hr/registry.py
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 | |
apply_identity_update
async
¶
Mutate any allowed field on the registered identity.
Designed for the MCP write surface, which is privileged and
must be able to update everything the REST API can. Only the
truly-immutable identifiers (id, name, department)
and the lifecycle status slot (which has its own
update_status path) are rejected.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
The agent identifier. |
required |
updates
|
dict[str, Any]
|
Mapping of field name to new value. |
required |
saved_by
|
str
|
Actor recorded in the version snapshot. |
required |
Returns:
| Type | Description |
|---|---|
AgentIdentity
|
Updated agent identity (a new frozen instance). |
Raises:
| Type | Description |
|---|---|
AgentNotFoundError
|
If the agent is not registered. |
ValueError
|
If |
Source code in src/synthorg/hr/registry.py
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 | |
update_autonomy
async
¶
Request an autonomy level change for an agent.
Mirrors the REST endpoint: the change is requested, never
applied directly. SECURITY_AUTONOMY_PROMOTION_REQUESTED is logged
for the audit trail; an approval item is enqueued when an
approval_store is wired so the queue can drive the human
review; SECURITY_AUTONOMY_PROMOTION_DENIED is logged because the
request did not produce an immediate runtime change.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
The agent whose autonomy is being changed. |
required |
update
|
AutonomyUpdate
|
The autonomy change request. |
required |
approval_store
|
ApprovalStoreProtocol | None
|
Optional approval store; when provided, the
request is enqueued and the returned |
None
|
Returns:
| Type | Description |
|---|---|
AutonomyUpdateResult
|
|
Raises:
| Type | Description |
|---|---|
AgentNotFoundError
|
If the agent is not registered. |
Source code in src/synthorg/hr/registry.py
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 | |
Hiring Service¶
hiring_service
¶
Hiring service.
Orchestrates the hiring pipeline: request creation, candidate generation, approval submission, and agent instantiation.
HiringService
¶
HiringService(
*, registry, approval_store=None, onboarding_service=None, default_model_config=None
)
Orchestrates the hiring pipeline.
Manages the lifecycle of hiring requests from creation through candidate generation, approval, and agent instantiation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
AgentRegistryService
|
Agent registry for registering new agents. |
required |
approval_store
|
ApprovalStoreProtocol | None
|
Optional approval store for human approval. |
None
|
onboarding_service
|
OnboardingService | None
|
Optional onboarding service to start onboarding after instantiation. |
None
|
default_model_config
|
ModelConfig | None
|
Optional default model configuration for newly created agents. Falls back to generic defaults if not provided. |
None
|
Source code in src/synthorg/hr/hiring_service.py
create_request
async
¶
create_request(
*,
requested_by,
department,
role,
level,
required_skills=(),
reason,
budget_limit_monthly=None,
template_name=None,
)
Create a new hiring request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
requested_by
|
NotBlankStr
|
Request initiator. |
required |
department
|
NotBlankStr
|
Target department. |
required |
role
|
NotBlankStr
|
Desired role. |
required |
level
|
str
|
Desired seniority level. |
required |
required_skills
|
tuple[NotBlankStr, ...]
|
Required skills. |
()
|
reason
|
NotBlankStr
|
Business justification. |
required |
budget_limit_monthly
|
float | None
|
Optional monthly budget limit. |
None
|
template_name
|
str | None
|
Template for candidate generation. |
None
|
Returns:
| Type | Description |
|---|---|
HiringRequest
|
The created hiring request. |
Source code in src/synthorg/hr/hiring_service.py
generate_candidate
async
¶
Generate a candidate card for a hiring request.
Builds a CandidateCard from role/level defaults. In the
future, this can be extended with template presets and LLM
customization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
HiringRequest
|
The hiring request to generate a candidate for. |
required |
Returns:
| Type | Description |
|---|---|
HiringRequest
|
Updated request with the new candidate appended. |
Source code in src/synthorg/hr/hiring_service.py
submit_for_approval
async
¶
Submit a candidate for approval.
If no approval store is configured, auto-approves the request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
HiringRequest
|
The hiring request. |
required |
candidate_id
|
str
|
ID of the candidate to approve. |
required |
Returns:
| Type | Description |
|---|---|
HiringRequest
|
Updated request with approval status. |
Raises:
| Type | Description |
|---|---|
InvalidCandidateError
|
If the candidate ID is not found. |
Source code in src/synthorg/hr/hiring_service.py
instantiate_agent
async
¶
Instantiate an agent from an approved hiring request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
HiringRequest
|
The approved hiring request. |
required |
Returns:
| Type | Description |
|---|---|
AgentIdentity
|
The newly created agent identity. |
Raises:
| Type | Description |
|---|---|
HiringApprovalRequiredError
|
If request is not approved. |
HiringRejectedError
|
If request was rejected. |
InvalidCandidateError
|
If no candidate is selected. |
HiringError
|
If instantiation fails. |
Source code in src/synthorg/hr/hiring_service.py
Onboarding Service¶
onboarding_service
¶
Onboarding service.
Manages agent onboarding checklists, step tracking, and automatic activation upon checklist completion.
OnboardingService
¶
Manages onboarding checklists and step tracking.
Creates checklists with all OnboardingStep values when
onboarding starts. When all steps are completed, automatically
transitions the agent to ACTIVE status via the registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
AgentRegistryService
|
Agent registry for status updates. |
required |
Source code in src/synthorg/hr/onboarding_service.py
start_onboarding
async
¶
Start onboarding for a newly hired agent.
Creates a checklist with all onboarding steps in PENDING state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
str
|
Agent to onboard. |
required |
Returns:
| Type | Description |
|---|---|
OnboardingChecklist
|
The created onboarding checklist. |
Raises:
| Type | Description |
|---|---|
OnboardingError
|
If a checklist already exists. |
Source code in src/synthorg/hr/onboarding_service.py
complete_step
async
¶
Mark an onboarding step as complete.
When all steps are completed, automatically transitions the agent to ACTIVE status.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
str
|
Agent being onboarded. |
required |
step
|
OnboardingStep
|
The step to complete. |
required |
notes
|
str
|
Optional notes for the step. |
''
|
Returns:
| Type | Description |
|---|---|
OnboardingChecklist
|
Updated onboarding checklist. |
Raises:
| Type | Description |
|---|---|
OnboardingError
|
If no checklist exists for the agent. |
Source code in src/synthorg/hr/onboarding_service.py
get_checklist
async
¶
Retrieve the onboarding checklist for an agent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
str
|
Agent to look up. |
required |
Returns:
| Type | Description |
|---|---|
OnboardingChecklist | None
|
The checklist, or None if not found. |
Source code in src/synthorg/hr/onboarding_service.py
Offboarding Service¶
offboarding_service
¶
Offboarding service.
Orchestrates the firing/offboarding pipeline: task reassignment, memory archival, team notification, and agent termination.
OffboardingService
¶
OffboardingService(
*,
registry,
reassignment_strategy=None,
archival_strategy=None,
memory_backend=None,
archival_store=None,
org_memory_backend=None,
message_bus=None,
task_repository=None,
)
Orchestrates the firing/offboarding pipeline.
Pipeline steps
- Get active tasks and reassign via strategy.
- Archive memory via archival strategy.
- Notify team via message bus.
- Update agent status to TERMINATED and return record.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
AgentRegistryService
|
Agent registry for status updates. |
required |
reassignment_strategy
|
TaskReassignmentStrategy | None
|
Strategy for task reassignment. When
|
None
|
archival_strategy
|
MemoryArchivalStrategy | None
|
Strategy for memory archival. When
|
None
|
memory_backend
|
MemoryBackend | None
|
Optional hot memory store. |
None
|
archival_store
|
ArchivalStore | None
|
Optional cold archival storage. |
None
|
org_memory_backend
|
OrgMemoryBackend | None
|
Optional org memory for promotion. |
None
|
message_bus
|
MessageBus | None
|
Optional message bus for notifications. |
None
|
task_repository
|
TaskRepository | None
|
Optional task repository for queries. |
None
|
Source code in src/synthorg/hr/offboarding_service.py
offboard
async
¶
Execute the full offboarding pipeline.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
FiringRequest
|
The firing request to process. |
required |
Returns:
| Type | Description |
|---|---|
OffboardingRecord
|
Record of the completed offboarding. |
Raises:
| Type | Description |
|---|---|
OffboardingError
|
If task reassignment fails (fatal). |
AgentNotFoundError
|
If the agent is not in the registry (fatal). |
Note
Memory archival and team notification failures are logged but non-fatal -- offboarding continues.
Source code in src/synthorg/hr/offboarding_service.py
Enums¶
enums
¶
HR domain enumerations.
HiringRequestStatus
¶
Bases: StrEnum
Status of a hiring request through the approval pipeline.
FiringReason
¶
Bases: StrEnum
Reason for agent termination.
OnboardingStep
¶
Bases: StrEnum
Steps in the agent onboarding checklist.
LifecycleEventType
¶
Bases: StrEnum
Type of agent lifecycle event.
ActivityEventType
¶
Bases: StrEnum
Event types produced by the activity feed timeline.
Superset of LifecycleEventType plus operational event types
generated from task metrics, cost records, tool invocations,
and delegation records.
PromotionDirection
¶
Bases: StrEnum
Direction of a seniority level change.
TrendDirection
¶
Bases: StrEnum
Direction of a performance metric trend.
Errors¶
errors
¶
HR domain error hierarchy.
All HR errors default to is_retryable = False. HR operations are
either deterministic lookups (agent registry, personality catalogue,
training session store) or write-ops against authoritative state
(hiring, promotion, pruning) where silent retries would double-apply.
Subclasses that genuinely represent a transient network/I/O failure
should override is_retryable = True explicitly.
HRError
¶
Bases: DomainError
Base error for all HR operations.
is_retryable defaults to False so the provider-retry layer
surfaces HR errors immediately; subclasses override to True
only for genuine transient I/O / network failures.
Source code in src/synthorg/core/domain_errors.py
HiringError
¶
HiringApprovalRequiredError
¶
Bases: HiringError
Hiring request requires approval before instantiation.
Source code in src/synthorg/core/domain_errors.py
HiringRejectedError
¶
InvalidCandidateError
¶
Bases: HiringError
Candidate card is invalid or does not exist on the request.
Source code in src/synthorg/core/domain_errors.py
FiringError
¶
OffboardingError
¶
TaskReassignmentError
¶
Bases: OffboardingError
Failed to reassign tasks from a departing agent.
Source code in src/synthorg/core/domain_errors.py
MemoryArchivalError
¶
Bases: OffboardingError
Failed to archive agent memories during offboarding.
Source code in src/synthorg/core/domain_errors.py
OnboardingError
¶
AgentRegistryError
¶
AgentNotFoundError
¶
Bases: AgentRegistryError
Agent not found in the registry.
Source code in src/synthorg/core/domain_errors.py
AgentAlreadyRegisteredError
¶
Bases: AgentRegistryError
Agent is already registered.
Source code in src/synthorg/core/domain_errors.py
PerformanceError
¶
InsufficientDataError
¶
Bases: PerformanceError
Not enough data points for a meaningful computation.
Source code in src/synthorg/core/domain_errors.py
PromotionError
¶
PromotionCooldownError
¶
Bases: PromotionError
Promotion is blocked by the cooldown period.
Source code in src/synthorg/core/domain_errors.py
PromotionApprovalRequiredError
¶
Bases: PromotionError
Promotion requires human approval before proceeding.
Source code in src/synthorg/core/domain_errors.py
PruningError
¶
PruningUnrestartableError
¶
Bases: PruningError
Raised when PruningService.start() is called after a timed-out stop.
Mirrors :class:BackupUnrestartableError: a stuck drain leaves an
orphan loop that may still hold references the new instance would
race; the canonical lifecycle pattern marks the service unrestartable
and forces operators to construct a fresh one.
Source code in src/synthorg/core/domain_errors.py
PersonalityError
¶
PersonalityNotFoundError
¶
Bases: PersonalityError
Personality preset not found in the catalogue.
Source code in src/synthorg/core/domain_errors.py
TrainingError
¶
TrainingSessionNotFoundError
¶
Bases: TrainingError
Training session not found in the session store.
Source code in src/synthorg/core/domain_errors.py
Performance¶
config
¶
Performance tracking configuration.
PerformanceConfig
pydantic-model
¶
Bases: BaseModel
Configuration for the performance tracking system.
Attributes:
| Name | Type | Description |
|---|---|---|
min_data_points |
int
|
Minimum data points for meaningful aggregation. |
windows |
tuple[NotBlankStr, ...]
|
Time window labels for rolling metrics. |
improving_threshold |
float
|
Slope threshold for improving trend. |
declining_threshold |
float
|
Slope threshold for declining trend. |
collaboration_weights |
dict[str, float] | None
|
Optional custom weights for collaboration scoring components. |
llm_sampling_rate |
float
|
Fraction of collaboration events sampled by LLM (0.01 = 1%). |
llm_sampling_model |
NotBlankStr | None
|
Model ID for LLM calibration sampling (None = disabled). |
calibration_retention_days |
int
|
Days to retain LLM calibration records. |
quality_judge_model |
NotBlankStr | None
|
Model ID for LLM quality judge (None = disabled). |
quality_judge_provider |
NotBlankStr | None
|
Provider name for LLM quality judge (None = auto from model ref). Requires quality_judge_model. |
quality_ci_weight |
float
|
Weight for CI signal in composite quality score (default 0.4). |
quality_llm_weight |
float
|
Weight for LLM judge in composite quality score (default 0.6). |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
min_data_points(int) -
windows(tuple[NotBlankStr, ...]) -
improving_threshold(float) -
declining_threshold(float) -
collaboration_weights(dict[str, float] | None) -
llm_sampling_rate(float) -
llm_sampling_model(NotBlankStr | None) -
calibration_retention_days(int) -
quality_judge_model(NotBlankStr | None) -
quality_judge_provider(NotBlankStr | None) -
quality_ci_weight(float) -
quality_llm_weight(float)
Validators:
-
_validate_quality_judge_provider_requires_model -
_validate_threshold_ordering -
_validate_quality_weights_sum
windows
pydantic-field
¶
windows = (NotBlankStr('7d'), NotBlankStr('30d'), NotBlankStr('90d'))
Time window labels for rolling metrics
declining_threshold
pydantic-field
¶
Slope threshold for declining trend
collaboration_weights
pydantic-field
¶
Custom weights for collaboration scoring components
llm_sampling_rate
pydantic-field
¶
Fraction of collaboration events sampled by LLM (0.01 = 1%)
llm_sampling_model
pydantic-field
¶
Model ID for LLM calibration sampling (None = disabled)
calibration_retention_days
pydantic-field
¶
Days to retain LLM calibration records
quality_judge_model
pydantic-field
¶
Model ID for LLM quality judge (None = disabled)
quality_judge_provider
pydantic-field
¶
Provider name for LLM quality judge (None = auto from model ref)
quality_ci_weight
pydantic-field
¶
Weight for CI signal in composite quality score. Together with quality_llm_weight, must sum to 1.0.
quality_llm_weight
pydantic-field
¶
Weight for LLM judge in composite quality score. Together with quality_ci_weight, must sum to 1.0.
models
¶
Performance tracking domain models.
Frozen Pydantic models for task metrics, collaboration metrics, quality/collaboration scoring results, trend detection, and rolling-window aggregates.
TaskMetricRecord
pydantic-model
¶
Bases: BaseModel
Record of a single task completion for performance tracking.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique record identifier. |
agent_id |
NotBlankStr
|
Agent who completed the task. |
task_id |
NotBlankStr
|
Task identifier. |
task_type |
TaskType
|
Classification of the task. |
started_at |
AwareDatetime | None
|
When the task started (None if not tracked). |
completed_at |
AwareDatetime
|
When the task was completed. |
is_success |
bool
|
Whether the task completed successfully. |
duration_seconds |
float
|
Wall-clock execution time. |
cost |
float
|
Numeric cost of the task, denominated in |
currency |
CurrencyCode
|
ISO 4217 currency code for |
turns_used |
int
|
Number of LLM turns used. |
tokens_used |
int
|
Total tokens consumed. |
quality_score |
float | None
|
Quality score (0.0-10.0), None if not scored. |
complexity |
Complexity
|
Estimated task complexity. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
agent_id(NotBlankStr) -
task_id(NotBlankStr) -
task_type(TaskType) -
started_at(AwareDatetime | None) -
completed_at(AwareDatetime) -
is_success(bool) -
duration_seconds(float) -
cost(float) -
currency(CurrencyCode) -
turns_used(int) -
tokens_used(int) -
quality_score(float | None) -
complexity(Complexity)
Validators:
-
_validate_temporal_ordering
CollaborationMetricRecord
pydantic-model
¶
Bases: BaseModel
Record of a collaboration behavior data point.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique record identifier. |
agent_id |
NotBlankStr
|
Agent being measured. |
recorded_at |
AwareDatetime
|
When the observation was recorded. |
delegation_success |
bool | None
|
Whether a delegation was successful. |
delegation_response_seconds |
float | None
|
Response time for a delegation. |
conflict_constructiveness |
float | None
|
How constructively conflict was handled. |
meeting_contribution |
float | None
|
Quality of meeting contribution. |
loop_triggered |
bool
|
Whether the agent triggered a delegation loop. |
handoff_completeness |
float | None
|
Completeness of task handoff (0.0-1.0). |
interaction_summary |
NotBlankStr | None
|
Text summary of the interaction for LLM calibration (None if not available). |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
agent_id(NotBlankStr) -
recorded_at(AwareDatetime) -
delegation_success(bool | None) -
delegation_response_seconds(float | None) -
conflict_constructiveness(float | None) -
meeting_contribution(float | None) -
loop_triggered(bool) -
handoff_completeness(float | None) -
interaction_summary(NotBlankStr | None)
delegation_response_seconds
pydantic-field
¶
Response time for a delegation
conflict_constructiveness
pydantic-field
¶
How constructively conflict was handled
loop_triggered
pydantic-field
¶
Whether the agent triggered a delegation loop
interaction_summary
pydantic-field
¶
Text summary of the interaction for LLM calibration
QualityScoreResult
pydantic-model
¶
Bases: BaseModel
Result of a quality scoring evaluation.
Attributes:
| Name | Type | Description |
|---|---|---|
score |
float
|
Overall quality score (0.0-10.0). |
strategy_name |
NotBlankStr
|
Name of the scoring strategy used. |
breakdown |
tuple[tuple[NotBlankStr, float], ...]
|
Score components as (name, value) pairs. |
confidence |
float
|
Confidence in the score (0.0-1.0). |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
score(float) -
strategy_name(NotBlankStr) -
breakdown(tuple[tuple[NotBlankStr, float], ...]) -
confidence(float)
CollaborationScoreResult
pydantic-model
¶
Bases: BaseModel
Result of a collaboration scoring evaluation.
Attributes:
| Name | Type | Description |
|---|---|---|
score |
float
|
Overall collaboration score (0.0-10.0). |
strategy_name |
NotBlankStr
|
Name of the scoring strategy used. |
component_scores |
tuple[tuple[NotBlankStr, float], ...]
|
Per-component scores as (name, value) pairs. |
confidence |
float
|
Confidence in the score (0.0-1.0). |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
score(float) -
strategy_name(NotBlankStr) -
component_scores(tuple[tuple[NotBlankStr, float], ...]) -
confidence(float) -
override_active(bool)
LlmCalibrationRecord
pydantic-model
¶
Bases: BaseModel
Record of an LLM calibration sample for collaboration scoring.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique record identifier. |
agent_id |
NotBlankStr
|
Agent being evaluated. |
sampled_at |
AwareDatetime
|
When the LLM evaluation occurred. |
interaction_record_id |
NotBlankStr
|
ID of the sampled CollaborationMetricRecord. |
llm_score |
float
|
LLM-assigned collaboration score (0.0-10.0). |
behavioral_score |
float
|
Behavioral strategy score at time of sampling. |
drift |
float
|
Absolute difference between LLM and behavioral scores (computed). |
rationale |
NotBlankStr
|
LLM's explanation for the score. |
model_used |
NotBlankStr
|
Which LLM model was used for evaluation. |
cost |
float
|
Numeric cost of the LLM call, denominated in |
currency |
CurrencyCode
|
ISO 4217 currency code for |
Config:
frozen:Trueallow_inf_nan:False
Fields:
-
id(NotBlankStr) -
agent_id(NotBlankStr) -
sampled_at(AwareDatetime) -
interaction_record_id(NotBlankStr) -
llm_score(float) -
behavioral_score(float) -
rationale(NotBlankStr) -
model_used(NotBlankStr) -
cost(float) -
currency(CurrencyCode)
interaction_record_id
pydantic-field
¶
ID of the sampled CollaborationMetricRecord
CollaborationOverride
pydantic-model
¶
Bases: _BaseOverride
Human-applied override for an agent's collaboration score.
Fields:
-
id(NotBlankStr) -
agent_id(NotBlankStr) -
score(float) -
reason(NotBlankStr) -
applied_by(NotBlankStr) -
applied_at(AwareDatetime) -
expires_at(AwareDatetime | None)
Validators:
-
_validate_expiration_ordering
QualityOverride
pydantic-model
¶
Bases: _BaseOverride
Human-applied override for an agent's quality score.
Fields:
-
id(NotBlankStr) -
agent_id(NotBlankStr) -
score(float) -
reason(NotBlankStr) -
applied_by(NotBlankStr) -
applied_at(AwareDatetime) -
expires_at(AwareDatetime | None)
Validators:
-
_validate_expiration_ordering
TrendResult
pydantic-model
¶
Bases: BaseModel
Result of a trend detection analysis.
Attributes:
| Name | Type | Description |
|---|---|---|
metric_name |
NotBlankStr
|
Name of the metric being trended. |
window_size |
NotBlankStr
|
Time window label (e.g. '7d', '30d'). |
direction |
TrendDirection
|
Detected trend direction. |
slope |
float
|
Computed slope of the trend line. |
data_point_count |
int
|
Number of data points used. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
metric_name(NotBlankStr) -
window_size(NotBlankStr) -
direction(TrendDirection) -
slope(float) -
data_point_count(int)
WindowMetrics
pydantic-model
¶
Bases: BaseModel
Aggregate metrics for a rolling time window.
Attributes:
| Name | Type | Description |
|---|---|---|
window_size |
NotBlankStr
|
Time window label (e.g. '7d', '30d'). |
data_point_count |
int
|
Number of records in the window. |
tasks_completed |
int
|
Number of successful tasks. |
tasks_failed |
int
|
Number of failed tasks. |
avg_quality_score |
float | None
|
Average quality score, None if insufficient data. |
avg_cost_per_task |
float | None
|
Average cost per task, None if insufficient data. |
currency |
CurrencyCode | None
|
ISO 4217 currency code for |
avg_completion_time_seconds |
float | None
|
Average time, None if insufficient data. |
avg_tokens_per_task |
float | None
|
Average tokens, None if insufficient data. |
success_rate |
float | None
|
Task success rate (0.0-1.0), None if no tasks. |
collaboration_score |
float | None
|
Collaboration score, None if not computed. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
window_size(NotBlankStr) -
data_point_count(int) -
tasks_completed(int) -
tasks_failed(int) -
avg_quality_score(float | None) -
avg_cost_per_task(float | None) -
currency(CurrencyCode | None) -
avg_completion_time_seconds(float | None) -
avg_tokens_per_task(float | None) -
success_rate(float | None) -
collaboration_score(float | None)
Validators:
-
_validate_task_counts -
_validate_currency_presence
CollaborationCalibration
pydantic-model
¶
Bases: BaseModel
Stable, ops-facing readout of the collaboration scoring strategy.
Returned by PerformanceTracker.get_collaboration_calibration for
the MCP synthorg_collaboration_get_calibration tool. The shape
is intentionally curated -- callers see strategy_name and the
bounded component_weights tuple, but they do not see strategy-
private internals. Swapping the underlying
:class:~synthorg.hr.performance.protocols.CollaborationScoringStrategy
therefore does not change the envelope shape MCP consumers depend on.
Attributes:
| Name | Type | Description |
|---|---|---|
agent_id |
NotBlankStr
|
The agent the calibration was computed for. |
strategy_name |
NotBlankStr
|
Name of the active scoring strategy. |
window_sizes |
tuple[NotBlankStr, ...]
|
Rolling-window labels the strategy aggregates over. |
component_weights |
tuple[tuple[NotBlankStr, float], ...]
|
Ordered tuple of |
active_override |
CollaborationOverride | None
|
Currently-active human override, if any. |
sample_size |
int
|
Number of collaboration samples backing the active
window. |
last_calibrated_at |
AwareDatetime | None
|
Timestamp of the most recent calibration
sample, or |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
agent_id(NotBlankStr) -
strategy_name(NotBlankStr) -
window_sizes(tuple[NotBlankStr, ...]) -
component_weights(tuple[tuple[NotBlankStr, float], ...]) -
active_override(CollaborationOverride | None) -
sample_size(int) -
last_calibrated_at(AwareDatetime | None)
AgentPerformanceSnapshot
pydantic-model
¶
Bases: BaseModel
Complete performance snapshot for an agent at a point in time.
Attributes:
| Name | Type | Description |
|---|---|---|
agent_id |
NotBlankStr
|
The agent being evaluated. |
computed_at |
AwareDatetime
|
When this snapshot was computed. |
windows |
tuple[WindowMetrics, ...]
|
Rolling window metrics. |
trends |
tuple[TrendResult, ...]
|
Detected trends per metric. |
overall_quality_score |
float | None
|
Aggregate quality score. |
overall_collaboration_score |
float | None
|
Aggregate collaboration score. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
agent_id(NotBlankStr) -
computed_at(AwareDatetime) -
windows(tuple[WindowMetrics, ...]) -
trends(tuple[TrendResult, ...]) -
overall_quality_score(float | None) -
overall_collaboration_score(float | None)
overall_collaboration_score
pydantic-field
¶
Aggregate collaboration score
tracker
¶
Performance tracker service.
Central service for recording and querying agent performance metrics. Delegates scoring, windowing, and trend detection to pluggable strategies.
PerformanceTracker
¶
PerformanceTracker(
*,
quality_strategy=None,
collaboration_strategy=None,
window_strategy=None,
trend_strategy=None,
config=None,
sampler=None,
override_store=None,
quality_override_store=None,
inflection_sink=None,
)
Central service for recording and querying agent performance metrics.
In-memory storage keyed by agent_id. Delegates scoring, windowing, and trend detection to injected strategy implementations.
When strategies are not provided, sensible defaults are constructed
(window and trend strategies use values from PerformanceConfig).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
quality_strategy
|
QualityScoringStrategy | None
|
Strategy for scoring task quality. |
None
|
collaboration_strategy
|
CollaborationScoringStrategy | None
|
Strategy for scoring collaboration. |
None
|
window_strategy
|
MetricsWindowStrategy | None
|
Strategy for computing rolling windows. |
None
|
trend_strategy
|
TrendDetectionStrategy | None
|
Strategy for detecting trends. |
None
|
config
|
PerformanceConfig | None
|
Performance tracking configuration. |
None
|
sampler
|
LlmCalibrationSampler | None
|
LLM calibration sampler (None = disabled). |
None
|
override_store
|
CollaborationOverrideStore | None
|
Collaboration override store (None = disabled). |
None
|
quality_override_store
|
QualityOverrideStore | None
|
Quality override store (None = disabled). |
None
|
Source code in src/synthorg/hr/performance/tracker.py
quality_override_store
property
¶
Return the quality override store, if configured.
clear
¶
Reset all recorded metrics for test isolation.
Cancels pending background tasks via Task.cancel() but does
not await them. This is a synchronous method intended for
use in sync test fixtures (where no running event loop is
available, or where the previous test's event loop is already
closed and awaiting would fail). Any in-flight work in those
tasks is discarded.
For production shutdown where tasks must drain cleanly, use
:meth:aclose instead -- it cancels and awaits.
Source code in src/synthorg/hr/performance/tracker.py
aclose
async
¶
Cancel and await all pending background tasks.
Should be called during application shutdown to prevent
RuntimeError: Task was destroyed but it is pending!
warnings.
Sets _closing under _metrics_lock before snapshotting
so concurrent record_collaboration_event / get_snapshot
calls (which schedule under the same lock) refuse to enqueue
new background tasks once shutdown has started. Without that
gate a task scheduled right after the snapshot would survive
aclose() with the result that the caller sees
aclose() returned while a live sampling / inflection task
keeps running and can still repopulate cache state.
Source code in src/synthorg/hr/performance/tracker.py
aclear
async
¶
Async-safe reset of all recorded metrics.
Acquires _metrics_lock so no recorder can observe a partial
clear and no reader can race the mutation of _task_metrics
/ _collab_metrics / _contributions /
_trend_direction_cache. Cancels pending background tasks
without awaiting them (matches :meth:clear semantics) so
the call is cheap in hot tests.
Production callers that must drain outstanding tasks cleanly
should call :meth:aclose instead.
Source code in src/synthorg/hr/performance/tracker.py
record_task_metric
async
¶
Record a task completion metric.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
record
|
TaskMetricRecord
|
The task metric record to store. |
required |
Returns:
| Type | Description |
|---|---|
TaskMetricRecord
|
The stored record. |
Source code in src/synthorg/hr/performance/tracker.py
record_coordination_contributions
async
¶
Store per-agent contributions from coordination.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
contributions
|
tuple[AgentContribution, ...]
|
Attribution records from a coordinated run. |
required |
Source code in src/synthorg/hr/performance/tracker.py
score_task_quality
async
¶
Score task quality and update the record.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
Agent who completed the task. |
required |
task_id
|
NotBlankStr
|
Task identifier. |
required |
task_result
|
TaskMetricRecord
|
Recorded task metrics. |
required |
acceptance_criteria
|
tuple[AcceptanceCriterion, ...]
|
Criteria to evaluate against. |
()
|
Returns:
| Type | Description |
|---|---|
TaskMetricRecord
|
Updated record with quality score. |
Source code in src/synthorg/hr/performance/tracker.py
record_collaboration_event
async
¶
Record a collaboration behavior data point.
If an LLM sampler is configured and the record has an
interaction_summary, the sampler is invoked probabilistically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
record
|
CollaborationMetricRecord
|
Collaboration metric record to store. |
required |
Source code in src/synthorg/hr/performance/tracker.py
get_collaboration_score
async
¶
Compute collaboration score for an agent.
Returns the active human override if one exists; otherwise delegates to the collaboration scoring strategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
Agent to evaluate. |
required |
now
|
AwareDatetime | None
|
Reference time for override expiration check (defaults to current UTC time). |
None
|
Returns:
| Type | Description |
|---|---|
CollaborationScoreResult
|
Collaboration score result. |
Source code in src/synthorg/hr/performance/tracker.py
get_collaboration_calibration
async
¶
Return a stable calibration readout for an agent.
The shape is deliberately curated -- strategy_name and the
bounded component_weights map describe the active scoring
strategy without leaking strategy-private internals. Swapping
the underlying strategy never changes the envelope shape.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
Agent to read calibration for. |
required |
Returns:
| Type | Description |
|---|---|
CollaborationCalibration
|
|
CollaborationCalibration
|
window labels, sample size, override (if any), and last |
CollaborationCalibration
|
calibration timestamp. |
Source code in src/synthorg/hr/performance/tracker.py
get_snapshots
async
¶
Compute performance snapshots for a batch of agents.
Order-preserving: the returned tuple has one entry per input
id in the same order. Entries are None when snapshot
computation raises (e.g. insufficient data, strategy error).
Single-agent log emissions are preserved so existing
observability pipelines keep working.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_ids
|
tuple[NotBlankStr, ...]
|
Ordered tuple of agent identifiers. |
required |
now
|
AwareDatetime | None
|
Reference time (defaults to current UTC time). |
None
|
Returns:
| Type | Description |
|---|---|
tuple[AgentPerformanceSnapshot | None, ...]
|
Tuple of snapshots (or |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/synthorg/hr/performance/tracker.py
get_snapshot
async
¶
Compute a full performance snapshot for an agent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
Agent to evaluate. |
required |
now
|
AwareDatetime | None
|
Reference time (defaults to current UTC time). |
None
|
Returns:
| Type | Description |
|---|---|
AgentPerformanceSnapshot
|
Complete performance snapshot with windows and trends. |
Source code in src/synthorg/hr/performance/tracker.py
get_task_metrics
¶
Query raw task metric records with optional filters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr | None
|
Filter by agent. |
None
|
since
|
AwareDatetime | None
|
Include records after this time. |
None
|
until
|
AwareDatetime | None
|
Include records before this time. |
None
|
Returns:
| Type | Description |
|---|---|
tuple[TaskMetricRecord, ...]
|
Matching task metric records. |
Source code in src/synthorg/hr/performance/tracker.py
get_collaboration_metrics
¶
Query collaboration metric records with optional filters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr | None
|
Filter by agent. |
None
|
since
|
AwareDatetime | None
|
Include records after this time. |
None
|
until
|
AwareDatetime | None
|
Include records before this time. |
None
|
Returns:
| Type | Description |
|---|---|
tuple[CollaborationMetricRecord, ...]
|
Matching collaboration metric records. |
Source code in src/synthorg/hr/performance/tracker.py
set_inflection_sink
async
¶
Atomically set the inflection sink under _metrics_lock.
The async counterpart to the sync :attr:inflection_sink
setter. Two concurrent callers will be serialized; exactly one
succeeds, the loser raises ValueError. Use this from any
async context where concurrent binding is possible (task
engine observers, rolling evolution triggers, etc.).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
InflectionSink | None
|
The inflection sink to assign. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If an inflection sink is already configured. |
Source code in src/synthorg/hr/performance/tracker.py
quality_protocol
¶
Quality scoring strategy protocol.
Defines the interface for pluggable quality scoring strategies that evaluate task completion quality (see Agents design page, D2).
QualityScoringStrategy
¶
Bases: Protocol
Strategy for scoring task completion quality.
Implementations evaluate task results against acceptance criteria and other quality signals to produce a normalized score.
score
async
¶
Score task completion quality.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
Agent who completed the task. |
required |
task_id
|
NotBlankStr
|
Task identifier. |
required |
task_result
|
TaskMetricRecord
|
Recorded task metrics. |
required |
acceptance_criteria
|
tuple[AcceptanceCriterion, ...]
|
Criteria to evaluate against. |
required |
Returns:
| Type | Description |
|---|---|
QualityScoreResult
|
Quality score result with breakdown and confidence. |
Source code in src/synthorg/hr/performance/quality_protocol.py
collaboration_protocol
¶
Collaboration scoring strategy protocol.
Defines the interface for pluggable collaboration scoring strategies that evaluate agent collaboration behavior (see Agents design page, D3).
CollaborationScoringStrategy
¶
Bases: Protocol
Strategy for scoring agent collaboration behavior.
Implementations evaluate behavioral telemetry records to produce a normalized collaboration score.
score
async
¶
Score agent collaboration behavior.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
Agent being evaluated. |
required |
records
|
tuple[CollaborationMetricRecord, ...]
|
Collaboration metric records to evaluate. |
required |
role_weights
|
dict[str, float] | None
|
Optional per-component weight overrides. |
None
|
Returns:
| Type | Description |
|---|---|
CollaborationScoreResult
|
Collaboration score result with component scores. |
Source code in src/synthorg/hr/performance/collaboration_protocol.py
trend_protocol
¶
Trend detection strategy protocol.
Defines the interface for pluggable trend detection strategies that analyze metric time series (see Agents design page, D12).
TrendDetectionStrategy
¶
Bases: Protocol
Strategy for detecting trends in metric time series.
Implementations analyze sequences of (timestamp, value) pairs to determine whether a metric is improving, stable, or declining.
detect
¶
Detect the trend direction in a metric time series.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metric_name
|
NotBlankStr
|
Name of the metric being analyzed. |
required |
values
|
tuple[tuple[AwareDatetime, float], ...]
|
Time series data as (timestamp, value) pairs. |
required |
window_size
|
NotBlankStr
|
Time window label for context. |
required |
Returns:
| Type | Description |
|---|---|
TrendResult
|
Trend detection result with direction and slope. |
Source code in src/synthorg/hr/performance/trend_protocol.py
Promotion¶
config
¶
Promotion configuration models.
Defines PromotionConfig and sub-configs for controlling
promotion/demotion behavior.
PromotionCriteriaConfig
pydantic-model
¶
Bases: BaseModel
Configuration for promotion criteria evaluation.
Attributes:
| Name | Type | Description |
|---|---|---|
min_criteria_met |
int
|
Minimum number of criteria that must be met. |
required_criteria |
tuple[NotBlankStr, ...]
|
Criteria names that must always be met. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
min_criteria_met(int) -
required_criteria(tuple[NotBlankStr, ...])
PromotionApprovalConfig
pydantic-model
¶
Bases: BaseModel
Configuration for promotion approval decisions.
Attributes:
| Name | Type | Description |
|---|---|---|
human_approval_from_level |
SeniorityLevel
|
Seniority level from which human approval is required for promotion. |
auto_demote_cost_saving |
bool
|
Auto-apply cost-saving demotions. |
human_demote_authority |
bool
|
Require human approval for authority-reducing demotions. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
ModelMappingConfig
pydantic-model
¶
Bases: BaseModel
Configuration for model mapping on seniority changes.
Attributes:
| Name | Type | Description |
|---|---|---|
model_follows_seniority |
bool
|
Whether model changes with seniority. |
seniority_model_map |
Mapping[str, str]
|
Explicit level-to-model overrides. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
model_follows_seniority(bool) -
seniority_model_map(Mapping[str, str])
Validators:
-
_validate_model_map_keys
PromotionConfig
pydantic-model
¶
Bases: BaseModel
Top-level promotion/demotion configuration.
Attributes:
| Name | Type | Description |
|---|---|---|
enabled |
bool
|
Whether the promotion subsystem is enabled. |
cooldown_hours |
int
|
Hours between consecutive promotions/demotions. |
criteria |
PromotionCriteriaConfig
|
Promotion criteria configuration. |
approval |
PromotionApprovalConfig
|
Promotion approval configuration. |
model_mapping |
ModelMappingConfig
|
Model mapping configuration. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
enabled(bool) -
cooldown_hours(int) -
criteria(PromotionCriteriaConfig) -
approval(PromotionApprovalConfig) -
model_mapping(ModelMappingConfig)
models
¶
Promotion domain models.
Frozen Pydantic models for promotion criteria results, evaluations, approval decisions, records, and requests.
CriterionResult
pydantic-model
¶
Bases: BaseModel
Result of a single promotion/demotion criterion evaluation.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
NotBlankStr
|
Criterion name. |
met |
bool
|
Whether the criterion was met. |
current_value |
float
|
Agent's current value for this criterion. |
threshold |
float
|
Required threshold value. |
weight |
float | None
|
Weight of this criterion (None if not weighted). |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
name(NotBlankStr) -
met(bool) -
current_value(float) -
threshold(float) -
weight(float | None)
PromotionEvaluation
pydantic-model
¶
Bases: BaseModel
Result of evaluating an agent for promotion or demotion.
Attributes:
| Name | Type | Description |
|---|---|---|
agent_id |
NotBlankStr
|
Agent being evaluated. |
current_level |
SeniorityLevel
|
Current seniority level. |
target_level |
SeniorityLevel
|
Target seniority level. |
direction |
PromotionDirection
|
Whether this is a promotion or demotion. |
criteria_results |
tuple[CriterionResult, ...]
|
Individual criterion results. |
required_criteria_met |
bool
|
Whether all required criteria are met. |
eligible |
bool
|
Whether the agent is eligible for the change. |
evaluated_at |
AwareDatetime
|
When the evaluation was performed. |
strategy_name |
NotBlankStr
|
Strategy that performed the evaluation. |
Config:
frozen:Trueallow_inf_nan:False
Fields:
-
agent_id(NotBlankStr) -
current_level(SeniorityLevel) -
target_level(SeniorityLevel) -
direction(PromotionDirection) -
criteria_results(tuple[CriterionResult, ...]) -
required_criteria_met(bool) -
eligible(bool) -
evaluated_at(AwareDatetime) -
strategy_name(NotBlankStr)
Validators:
-
_validate_direction_consistency
PromotionApprovalDecision
pydantic-model
¶
Bases: BaseModel
Decision on whether a promotion needs human approval.
Attributes:
| Name | Type | Description |
|---|---|---|
auto_approve |
bool
|
Whether the promotion can be auto-approved. |
reason |
NotBlankStr
|
Explanation for the decision. |
Config:
frozen:Trueallow_inf_nan:False
Fields:
-
auto_approve(bool) -
reason(NotBlankStr)
PromotionRecord
pydantic-model
¶
Bases: BaseModel
Record of a completed promotion or demotion.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique record identifier. |
agent_id |
NotBlankStr
|
Agent who was promoted/demoted. |
agent_name |
NotBlankStr
|
Agent display name. |
old_level |
SeniorityLevel
|
Previous seniority level. |
new_level |
SeniorityLevel
|
New seniority level. |
direction |
PromotionDirection
|
Whether this was a promotion or demotion. |
evaluation |
PromotionEvaluation
|
The evaluation that led to this change. |
approved_by |
NotBlankStr | None
|
Who approved the change ("auto" if auto-approved, "human" if human-approved via approval_id). |
approval_id |
NotBlankStr | None
|
Approval item ID if human-approved. |
effective_at |
AwareDatetime
|
When the change took effect. |
initiated_by |
NotBlankStr
|
Who initiated the promotion process. |
model_changed |
bool
|
Whether the model was changed. |
old_model_id |
NotBlankStr | None
|
Previous model ID (None if not changed). |
new_model_id |
NotBlankStr | None
|
New model ID (None if not changed). |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
agent_id(NotBlankStr) -
agent_name(NotBlankStr) -
old_level(SeniorityLevel) -
new_level(SeniorityLevel) -
direction(PromotionDirection) -
evaluation(PromotionEvaluation) -
approved_by(NotBlankStr | None) -
approval_id(NotBlankStr | None) -
effective_at(AwareDatetime) -
initiated_by(NotBlankStr) -
model_changed(bool) -
old_model_id(NotBlankStr | None) -
new_model_id(NotBlankStr | None)
Validators:
-
_validate_model_fields
PromotionRequest
pydantic-model
¶
Bases: BaseModel
A pending promotion or demotion request.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique request identifier. |
agent_id |
NotBlankStr
|
Agent being promoted/demoted. |
agent_name |
NotBlankStr
|
Agent display name. |
current_level |
SeniorityLevel
|
Current seniority level. |
target_level |
SeniorityLevel
|
Target seniority level. |
direction |
PromotionDirection
|
Whether this is a promotion or demotion. |
evaluation |
PromotionEvaluation
|
The evaluation supporting this request. |
status |
ApprovalStatus
|
Current approval status. |
created_at |
AwareDatetime
|
When the request was created. |
approval_id |
NotBlankStr | None
|
Linked approval item ID (for human approval). |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
agent_id(NotBlankStr) -
agent_name(NotBlankStr) -
current_level(SeniorityLevel) -
target_level(SeniorityLevel) -
direction(PromotionDirection) -
evaluation(PromotionEvaluation) -
status(ApprovalStatus) -
created_at(AwareDatetime) -
approval_id(NotBlankStr | None)
service
¶
Promotion service orchestrator.
Central service for managing agent promotions and demotions, including criteria evaluation, approval decisions, model mapping, and trust integration.
PromotionService
¶
PromotionService(
*,
criteria_strategy,
approval_strategy,
model_mapping_strategy,
registry,
tracker,
config,
approval_store=None,
trust_service=None,
on_notification=None,
)
Orchestrates agent promotions and demotions.
Coordinates criteria evaluation, approval decisions, model mapping, registry updates, and optional trust re-evaluation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
criteria_strategy
|
PromotionCriteriaStrategy
|
Strategy for evaluating promotion criteria. |
required |
approval_strategy
|
PromotionApprovalStrategy
|
Strategy for approval decisions. |
required |
model_mapping_strategy
|
ModelMappingStrategy
|
Strategy for model resolution. |
required |
registry
|
AgentRegistryService
|
Agent registry service. |
required |
tracker
|
PerformanceTracker
|
Performance tracker. |
required |
config
|
PromotionConfig
|
Promotion configuration. |
required |
approval_store
|
ApprovalStoreProtocol | None
|
Optional approval store for human approval. |
None
|
trust_service
|
TrustService | None
|
Optional trust service for re-evaluation. |
None
|
on_notification
|
PromotionNotificationCallback | None
|
Optional callback to notify agents/teams of promotion or demotion events. Wired by the communication layer when available. |
None
|
Source code in src/synthorg/hr/promotion/service.py
evaluate_promotion
async
¶
Evaluate whether an agent qualifies for promotion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
Agent to evaluate. |
required |
Returns:
| Type | Description |
|---|---|
PromotionEvaluation
|
Promotion evaluation result. |
Raises:
| Type | Description |
|---|---|
PromotionError
|
If the agent cannot be promoted. |
Source code in src/synthorg/hr/promotion/service.py
evaluate_demotion
async
¶
Evaluate whether an agent should be demoted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
Agent to evaluate. |
required |
Returns:
| Type | Description |
|---|---|
PromotionEvaluation
|
Demotion evaluation result. |
Raises:
| Type | Description |
|---|---|
PromotionError
|
If the agent cannot be demoted. |
Source code in src/synthorg/hr/promotion/service.py
request_promotion
async
¶
Create a promotion/demotion request.
Checks cooldown, evaluates approval decision, and creates an approval item if human approval is needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
Agent to promote/demote. |
required |
evaluation
|
PromotionEvaluation
|
The evaluation result. |
required |
initiated_by
|
NotBlankStr
|
Who initiated the request. |
_SYSTEM_INITIATOR
|
Returns:
| Type | Description |
|---|---|
PromotionRequest
|
Promotion request. |
Raises:
| Type | Description |
|---|---|
PromotionCooldownError
|
If in cooldown period. |
PromotionError
|
If agent not found. |
Source code in src/synthorg/hr/promotion/service.py
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | |
apply_promotion
async
¶
Apply a promotion/demotion from an approved request.
Updates the agent's seniority level, resolves model mapping, triggers trust re-evaluation, and records the lifecycle event.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
PromotionRequest
|
Approved promotion request. |
required |
initiated_by
|
NotBlankStr
|
Who initiated the application. |
_SYSTEM_INITIATOR
|
Returns:
| Type | Description |
|---|---|
PromotionRecord
|
Promotion record. |
Raises:
| Type | Description |
|---|---|
PromotionApprovalRequiredError
|
If request is not approved. |
PromotionError
|
If agent not found. |
Source code in src/synthorg/hr/promotion/service.py
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 | |
get_promotion_history
¶
Get promotion/demotion history for an agent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
Agent identifier. |
required |
Returns:
| Type | Description |
|---|---|
tuple[PromotionRecord, ...]
|
Tuple of promotion records. |
Source code in src/synthorg/hr/promotion/service.py
is_in_cooldown
¶
Check whether an agent is in the promotion cooldown period.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
Agent identifier. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if in cooldown. |
Source code in src/synthorg/hr/promotion/service.py
model_mapping_protocol
¶
Model mapping strategy protocol.
Defines the pluggable interface for mapping seniority levels to LLM model identifiers.
ModelMappingStrategy
¶
Bases: Protocol
Protocol for mapping seniority to LLM models.
Implementations determine which model an agent should use after a seniority level change.
resolve_model
¶
Resolve the model for an agent at a new seniority level.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_identity
|
AgentIdentity
|
The agent's current identity. |
required |
new_level
|
SeniorityLevel
|
The new seniority level. |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
New model_id, or None if no change needed. |
Source code in src/synthorg/hr/promotion/model_mapping_protocol.py
criteria_protocol
¶
Promotion criteria strategy protocol.
Defines the pluggable interface for evaluating promotion/demotion criteria.
PromotionCriteriaStrategy
¶
Bases: Protocol
Protocol for promotion criteria evaluation.
Implementations define what criteria must be met for an agent to be promoted or demoted between seniority levels.
evaluate
async
¶
Evaluate whether an agent meets criteria for level change.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
Agent to evaluate. |
required |
current_level
|
SeniorityLevel
|
Current seniority level. |
required |
target_level
|
SeniorityLevel
|
Target seniority level. |
required |
snapshot
|
AgentPerformanceSnapshot
|
Agent performance snapshot. |
required |
Returns:
| Type | Description |
|---|---|
PromotionEvaluation
|
Evaluation result with criteria details. |
Source code in src/synthorg/hr/promotion/criteria_protocol.py
approval_protocol
¶
Promotion approval strategy protocol.
Defines the pluggable interface for deciding whether promotions require human approval.
PromotionApprovalStrategy
¶
Bases: Protocol
Protocol for promotion approval decisions.
Implementations determine whether a promotion/demotion can be auto-approved or requires human intervention.
decide
async
¶
Decide whether a promotion needs human approval.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
evaluation
|
PromotionEvaluation
|
The promotion evaluation result. |
required |
agent_identity
|
AgentIdentity
|
The agent's current identity. |
required |
Returns:
| Type | Description |
|---|---|
PromotionApprovalDecision
|
Approval decision. |
Source code in src/synthorg/hr/promotion/approval_protocol.py
Pruning¶
models
¶
Pruning domain models.
Frozen Pydantic models for pruning evaluations, requests, records, and service configuration.
PruningEvaluation
pydantic-model
¶
Bases: BaseModel
Result of a pruning policy evaluation.
Attributes:
| Name | Type | Description |
|---|---|---|
agent_id |
NotBlankStr
|
Agent being evaluated. |
eligible |
bool
|
Whether agent should be pruned. |
reasons |
tuple[NotBlankStr, ...]
|
Human-readable justifications. |
scores |
dict[str, float]
|
Debug scores from evaluation criteria. |
policy_name |
NotBlankStr
|
Which policy produced this evaluation. |
snapshot |
AgentPerformanceSnapshot
|
Performance snapshot used for evaluation. |
evaluated_at |
AwareDatetime
|
When evaluation occurred. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
agent_id(NotBlankStr) -
eligible(bool) -
reasons(tuple[NotBlankStr, ...]) -
scores(dict[str, float]) -
policy_name(NotBlankStr) -
snapshot(AgentPerformanceSnapshot) -
evaluated_at(AwareDatetime)
Validators:
-
_validate_eligible_reasons
PruningRequest
pydantic-model
¶
Bases: BaseModel
Request to prune an agent pending human approval.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique request identifier. |
agent_id |
NotBlankStr
|
Agent to be pruned. |
agent_name |
NotBlankStr
|
Agent's display name. |
evaluation |
PruningEvaluation
|
The evaluation result. |
approval_id |
NotBlankStr
|
Associated approval item ID. |
status |
ApprovalStatus
|
Current approval status. |
created_at |
AwareDatetime
|
When request was created. |
decided_at |
AwareDatetime | None
|
When approval decision was made. |
decided_by |
NotBlankStr | None
|
Who made the approval decision. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
agent_id(NotBlankStr) -
agent_name(NotBlankStr) -
evaluation(PruningEvaluation) -
approval_id(NotBlankStr) -
status(ApprovalStatus) -
created_at(AwareDatetime) -
decided_at(AwareDatetime | None) -
decided_by(NotBlankStr | None)
Validators:
-
_validate_decision_fields
PruningRecord
pydantic-model
¶
Bases: BaseModel
Record of a completed pruning process.
Attributes:
| Name | Type | Description |
|---|---|---|
agent_id |
NotBlankStr
|
Agent who was pruned. |
agent_name |
NotBlankStr
|
Agent's display name. |
pruning_request_id |
NotBlankStr
|
Associated pruning request. |
firing_request_id |
NotBlankStr
|
Firing request ID from offboarding. |
reason |
NotBlankStr
|
Why agent was pruned. |
approval_id |
NotBlankStr
|
Which approval authorized it. |
initiated_by |
NotBlankStr
|
System or human who initiated. |
created_at |
AwareDatetime
|
When process started. |
completed_at |
AwareDatetime
|
When process finished. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
agent_id(NotBlankStr) -
agent_name(NotBlankStr) -
pruning_request_id(NotBlankStr) -
firing_request_id(NotBlankStr) -
reason(NotBlankStr) -
approval_id(NotBlankStr) -
initiated_by(NotBlankStr) -
created_at(AwareDatetime) -
completed_at(AwareDatetime)
Validators:
-
_validate_temporal_order
PruningJobRun
pydantic-model
¶
Bases: BaseModel
Metadata about a single pruning scheduler cycle.
Attributes:
| Name | Type | Description |
|---|---|---|
job_id |
NotBlankStr
|
Unique cycle identifier. |
run_at |
AwareDatetime
|
When the cycle started. |
agents_evaluated |
int
|
Count of agents checked. |
agents_eligible |
int
|
Count found eligible for pruning. |
approval_requests_created |
int
|
Count of new approvals. |
elapsed_seconds |
float
|
How long the cycle took. |
errors |
tuple[NotBlankStr, ...]
|
Non-fatal errors encountered. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
job_id(NotBlankStr) -
run_at(AwareDatetime) -
agents_evaluated(int) -
agents_eligible(int) -
approval_requests_created(int) -
elapsed_seconds(float) -
errors(tuple[NotBlankStr, ...])
Validators:
-
_validate_count_relationships
PruningServiceConfig
pydantic-model
¶
Bases: BaseModel
Configuration for the pruning service.
Attributes:
| Name | Type | Description |
|---|---|---|
evaluation_interval_seconds |
float
|
How often to run pruning cycles. |
max_approvals_per_cycle |
int
|
Limit on approvals created per cycle. |
approval_expiry_days |
int
|
Days until pending approval expires. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
evaluation_interval_seconds(float) -
max_approvals_per_cycle(int) -
approval_expiry_days(int)
policy
¶
Pruning policy protocol and implementations.
Defines pluggable strategies for evaluating whether an agent should be pruned based on performance data.
PruningPolicy
¶
Bases: Protocol
Strategy for evaluating whether an agent should be pruned.
evaluate
async
¶
Evaluate if agent should be pruned based on performance data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
The agent being evaluated. |
required |
snapshot
|
AgentPerformanceSnapshot
|
Current performance snapshot. |
required |
Returns:
| Type | Description |
|---|---|
PruningEvaluation
|
Evaluation result with eligibility and reasons. |
Source code in src/synthorg/hr/pruning/policy.py
ThresholdPruningPolicyConfig
pydantic-model
¶
Bases: BaseModel
Configuration for threshold-based pruning.
Attributes:
| Name | Type | Description |
|---|---|---|
quality_threshold |
float
|
Quality score floor (0-10). |
collaboration_threshold |
float
|
Collaboration score floor (0-10). |
minimum_consecutive_windows |
int
|
Windows that must be below threshold. |
minimum_window_data_points |
int
|
Minimum records to evaluate a window. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
quality_threshold(float) -
collaboration_threshold(float) -
minimum_consecutive_windows(int) -
minimum_window_data_points(int)
ThresholdPruningPolicy
¶
Prune agents with quality and collaboration below thresholds.
Agent is eligible if N+ consecutive windows (ordered by size)
have both avg_quality_score and collaboration_score strictly
below the configured thresholds, with sufficient data points.
Windows with None scores or insufficient data points break
the consecutive streak.
Source code in src/synthorg/hr/pruning/policy.py
evaluate
async
¶
Check quality/collaboration against thresholds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
The agent being evaluated. |
required |
snapshot
|
AgentPerformanceSnapshot
|
Current performance snapshot. |
required |
Returns:
| Type | Description |
|---|---|
PruningEvaluation
|
Evaluation result with eligibility and reasons. |
Source code in src/synthorg/hr/pruning/policy.py
TrendPruningPolicyConfig
pydantic-model
¶
Bases: BaseModel
Configuration for trend-based pruning.
Attributes:
| Name | Type | Description |
|---|---|---|
minimum_data_points_per_window |
int
|
Min data points per trend window. |
metric_name |
NotBlankStr
|
Which metric to track for trend evaluation. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
minimum_data_points_per_window
pydantic-field
¶
Minimum data points per trend window
metric_name
pydantic-field
¶
metric_name = NotBlankStr('quality_score')
Metric to track for trend evaluation
TrendPruningPolicy
¶
Prune agents with sustained negative trends across all windows.
Agent is eligible if all three windows (7d, 30d, 90d) show
DECLINING direction for the configured metric, with sufficient
data points per window.
Trends with INSUFFICIENT_DATA direction or below minimum data
points are treated as non-declining (agent not eligible).
Source code in src/synthorg/hr/pruning/policy.py
evaluate
async
¶
Check all windows for consistent declining trends.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent_id
|
NotBlankStr
|
The agent being evaluated. |
required |
snapshot
|
AgentPerformanceSnapshot
|
Current performance snapshot. |
required |
Returns:
| Type | Description |
|---|---|
PruningEvaluation
|
Evaluation result with eligibility and reasons. |
Source code in src/synthorg/hr/pruning/policy.py
service
¶
Pruning service -- performance-driven agent removal with human approval.
Periodically evaluates active agents against pruning policies, creates approval items for eligible candidates, and delegates to OffboardingService once human approval is granted.
Note
_pending_requests and _processed_approval_ids are in-memory
only. If the service restarts, already-decided approvals may be
reprocessed. The pruning_request_id stored in approval metadata
mitigates data loss for the audit trail, but full durability requires
a persistent backend (planned).
PruningService
¶
PruningService(
*,
policies,
registry,
tracker,
approval_store,
offboarding_service,
config=None,
on_notification=None,
)
Orchestrates performance-driven agent pruning with human approval.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policies
|
tuple[PruningPolicy, ...]
|
Pruning policy strategies to evaluate. |
required |
registry
|
AgentRegistryService
|
Agent registry for listing active agents. |
required |
tracker
|
PerformanceTracker
|
Performance tracker for snapshots. |
required |
approval_store
|
ApprovalStoreProtocol
|
Approval store for human decisions. |
required |
offboarding_service
|
OffboardingService
|
Service to delegate offboarding to. |
required |
config
|
PruningServiceConfig | None
|
Pruning service configuration. |
None
|
on_notification
|
Callable[[PruningRecord], Awaitable[None]] | None
|
Optional callback for completion notifications. |
None
|
Source code in src/synthorg/hr/pruning/service.py
start
async
¶
Start the background pruning scheduler.
Idempotent + concurrent-safe per docs/reference/lifecycle-sync.md:
serialises on self._lifecycle_lock so concurrent callers
cannot double-spawn the run loop.
Source code in src/synthorg/hr/pruning/service.py
stop
async
¶
Stop the background scheduler gracefully.
First signals the run loop to exit cleanly via _stop_event
and waits up to _stop_drain_timeout_seconds for the
in-flight pruning cycle to finish. Only escalates to
task.cancel() if the cooperative drain times out -- on
timeout the service is also marked unrestartable so a fresh
start() does not stack a second loop on top of the orphan
task that may still own pruning state.
Source code in src/synthorg/hr/pruning/service.py
wake
¶
run_pruning_cycle
async
¶
Execute a single pruning evaluation cycle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
now
|
datetime | None
|
Override for current time (testing). |
None
|
Returns:
| Type | Description |
|---|---|
PruningJobRun
|
Job run metadata with cycle statistics. |