pyagent-patterns API Reference¶
Base Classes¶
pyagent_patterns.base.Message
dataclass
¶
A single message in an agent conversation.
Attributes:
| Name | Type | Description |
|---|---|---|
role |
Role
|
The sender role (system, user, assistant, tool). |
content |
str
|
The text content of the message. |
name |
str | None
|
Optional agent name for multi-agent conversations. |
metadata |
dict[str, Any]
|
Arbitrary key-value metadata attached to the message. |
Source code in packages/pyagent-patterns/src/pyagent_patterns/base.py
pyagent_patterns.base.Agent
dataclass
¶
An LLM-backed agent with a name, system prompt, and callable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Human-readable agent name. |
required |
llm
|
LLMCallable
|
The LLM callable to use for this agent. |
required |
system_prompt
|
str
|
Optional system prompt prepended to every call. |
''
|
description
|
str
|
Description of the agent's purpose (for routing/selection). |
''
|
Optional hooks (set via setter methods — no constructor change): _trace_bus: Emit agent_start/agent_end trace events. _context_ledger: Read context before LLM call; write output after. _compressor: Compress agent output before returning. _cost_tracker: Record cost per LLM call.
Source code in packages/pyagent-patterns/src/pyagent_patterns/base.py
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 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 | |
run(messages)
async
¶
Send messages to the LLM and return an assistant message.
When hooks are wired the execution order is:
1. Emit agent_start trace event
2. Prepend context from ledger as messages
3. Call LLM
4. Record cost
5. Compress output
6. Write result to context ledger
7. Emit agent_end trace event with timing/tokens
Source code in packages/pyagent-patterns/src/pyagent_patterns/base.py
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 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 | |
set_compressor(compressor)
¶
Attach a MessageCompressor — compresses output before returning.
set_context(ledger)
¶
Attach a ContextLedger — reads context before LLM, writes output after.
set_cost_tracker(tracker)
¶
set_trace_bus(bus)
¶
Attach a TraceEventBus — emits agent_start/agent_end events on run().
pyagent_patterns.base.Pattern
¶
Bases: ABC
Abstract base class for all multi-agent patterns.
Subclasses must implement _execute. The run method handles timing,
context creation, and metadata collection.
Optional hooks
_trace_bus: Emit pattern_start/pattern_end trace events.
Source code in packages/pyagent-patterns/src/pyagent_patterns/base.py
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 353 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 | |
pattern_type
abstractmethod
property
¶
Return the pattern type name (e.g., 'supervisor', 'debate').
run(task, context=None)
async
¶
Execute the pattern on the given task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
str
|
The user task or prompt. |
required |
context
|
Context | None
|
Optional existing context. Created automatically if None. |
None
|
Returns:
| Type | Description |
|---|---|
Result
|
Result with output, messages, metadata, timing, and cost estimates. |
Source code in packages/pyagent-patterns/src/pyagent_patterns/base.py
set_trace_bus(bus)
¶
Attach a TraceEventBus — emits pattern_start/pattern_end on run().
stream(task, context=None)
async
¶
Stream partial results as they become available.
Default implementation runs the full pattern and yields the result. Subclasses can override for true streaming.
Source code in packages/pyagent-patterns/src/pyagent_patterns/base.py
pyagent_patterns.base.Context
dataclass
¶
Shared execution context for a pattern run.
Attributes:
| Name | Type | Description |
|---|---|---|
task |
str
|
The original user task/prompt. |
messages |
list[Message]
|
Accumulated message history. |
metadata |
dict[str, Any]
|
Arbitrary shared state across agents. |
parent_id |
str | None
|
ID of the parent context (for nested patterns). |
Source code in packages/pyagent-patterns/src/pyagent_patterns/base.py
child(task=None)
¶
Create a child context for nested pattern execution.
Source code in packages/pyagent-patterns/src/pyagent_patterns/base.py
pyagent_patterns.base.Result
dataclass
¶
Outcome of a pattern execution.
Attributes:
| Name | Type | Description |
|---|---|---|
output |
str
|
The final output text. |
messages |
list[Message]
|
All messages generated during execution. |
metadata |
dict[str, Any]
|
Pattern-specific metadata (rounds, consensus, votes, etc.). |
duration_seconds |
float
|
Wall-clock execution time. |
token_estimate |
int
|
Rough estimate of total tokens consumed. |
cost_estimate |
float
|
Rough estimate of total cost in USD. |
Source code in packages/pyagent-patterns/src/pyagent_patterns/base.py
Orchestration (Tier 1)¶
pyagent_patterns.orchestration.supervisor.Supervisor
¶
Bases: Pattern
Classify → route → collect orchestration pattern.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
classifier
|
Agent
|
Agent that classifies the task into a route key. |
required |
routes
|
dict[str, Agent]
|
Mapping of route keys to specialist agents. |
required |
formatter
|
Agent | None
|
Optional agent that formats the final response. |
None
|
default_route
|
str | None
|
Key to use when classification doesn't match any route. |
None
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/orchestration/supervisor.py
pyagent_patterns.orchestration.pipeline.Pipeline
¶
Bases: Pattern
Sequential stage chain — output of stage N becomes input of stage N+1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stages
|
list[Agent]
|
Ordered list of agents, each processing the previous output. |
required |
Source code in packages/pyagent-patterns/src/pyagent_patterns/orchestration/pipeline.py
stream(task, context=None)
async
¶
Stream stage completions as they finish.
Source code in packages/pyagent-patterns/src/pyagent_patterns/orchestration/pipeline.py
pyagent_patterns.orchestration.fan_out_fan_in.FanOutFanIn
¶
Bases: Pattern
Parallel execution with result aggregation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agents
|
list[Agent]
|
List of agents to run in parallel on the same task. |
required |
aggregator
|
Agent
|
Agent that combines all parallel outputs into one. |
required |
Source code in packages/pyagent-patterns/src/pyagent_patterns/orchestration/fan_out_fan_in.py
stream(task, context=None)
async
¶
Stream individual agent results as they complete.
Source code in packages/pyagent-patterns/src/pyagent_patterns/orchestration/fan_out_fan_in.py
pyagent_patterns.orchestration.hierarchical.Hierarchical
¶
Bases: Pattern
Manager → Team Leads → Workers hierarchical coordination.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
manager
|
Agent
|
Top-level manager that decomposes work and synthesizes results. |
required |
teams
|
list[Team]
|
List of teams, each with a lead and workers. |
required |
Source code in packages/pyagent-patterns/src/pyagent_patterns/orchestration/hierarchical.py
pyagent_patterns.orchestration.orchestrator_workers.OrchestratorWorkers
¶
Bases: Pattern
Dynamic task delegation: orchestrator plans → workers execute → synthesize.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
orchestrator
|
Agent
|
Agent that plans the work and synthesizes results. |
required |
workers
|
list[Agent]
|
Pool of available worker agents. The orchestrator selects from these. |
required |
Source code in packages/pyagent-patterns/src/pyagent_patterns/orchestration/orchestrator_workers.py
Resolution (Tier 2)¶
pyagent_patterns.resolution.self_reflection.SelfReflection
¶
Bases: Pattern
Generate → critique → refine iterative loop.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
Agent
|
The agent that generates and refines output. |
required |
critic
|
Agent | None
|
Optional separate critic agent. If None, the same agent self-critiques. |
None
|
max_rounds
|
int
|
Maximum number of generate-critique rounds. |
3
|
stop_phrase
|
str
|
If the critic's response contains this phrase, stop early. |
'APPROVED'
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/resolution/self_reflection.py
pyagent_patterns.resolution.cross_reflection.CrossReflection
¶
Bases: Pattern
Peer review: one agent generates, another reviews, generator revises.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
generator
|
Agent
|
Agent that produces the initial output and revisions. |
required |
reviewer
|
Agent
|
Agent that reviews and provides feedback. |
required |
max_rounds
|
int
|
Maximum number of generate-review-revise cycles. |
2
|
stop_phrase
|
str
|
If reviewer says this, stop early. |
'APPROVED'
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/resolution/cross_reflection.py
pyagent_patterns.resolution.debate.Debate
¶
Bases: Pattern
Structured adversarial debate with judge resolution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
debaters
|
list[Agent]
|
List of agents, each arguing a different position. |
required |
judge
|
Agent
|
Agent that evaluates arguments and renders final decision. |
required |
rounds
|
int
|
Number of argumentation rounds. |
3
|
positions
|
list[str] | None
|
Optional list of position labels (e.g., ["BUY", "SELL"]). If not provided, positions are assigned as "Position 1", "Position 2", etc. |
None
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/resolution/debate.py
pyagent_patterns.resolution.voting.Voting
¶
Bases: Pattern
Independent voting with configurable aggregation strategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
voters
|
list[Agent]
|
List of agents that each cast a vote. |
required |
strategy
|
VotingStrategy
|
Voting strategy (majority or weighted). |
MAJORITY
|
weights
|
list[float] | None
|
Optional per-agent weights for weighted voting. Must match length of voters. Defaults to equal weights. |
None
|
normalize
|
bool
|
If True, ask each voter to respond with a concise answer suitable for comparison. |
True
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/resolution/voting.py
pyagent_patterns.resolution.evaluator_optimizer.EvaluatorOptimizer
¶
Bases: Pattern
Generate → evaluate → revise loop with explicit evaluation criteria.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
generator
|
Agent
|
Agent that produces and revises output. |
required |
evaluator
|
Agent
|
Agent that scores output against criteria. |
required |
criteria
|
list[str] | None
|
List of evaluation criteria the evaluator checks. |
None
|
max_rounds
|
int
|
Maximum optimization rounds. |
3
|
pass_threshold
|
int
|
Score (1-10) at which the output is considered acceptable. |
7
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/resolution/evaluator_optimizer.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | |
Structural (Tier 3)¶
pyagent_patterns.structural.role_based.RoleBased
¶
Bases: Pattern
Agents with distinct roles collaborate in structured rounds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agents
|
list[Agent]
|
List of role-specialized agents (order matters for turn-taking). |
required |
rounds
|
int
|
Number of communication rounds. |
1
|
shared_context
|
bool
|
If True, all agents see all prior messages. If False, each agent only sees the immediately preceding message. |
True
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/structural/role_based.py
pyagent_patterns.structural.layered.Layered
¶
Bases: Pattern
Hierarchical layers of agents with increasing abstraction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[Layer]
|
Ordered list of layers from bottom (data) to top (synthesis). |
required |
Source code in packages/pyagent-patterns/src/pyagent_patterns/structural/layered.py
pyagent_patterns.structural.topology.Topology
¶
Bases: Pattern
Configurable agent communication topology.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agents
|
list[Agent]
|
List of agents participating in the topology. |
required |
topology
|
TopologyType
|
The communication structure (chain, star, mesh). |
CHAIN
|
hub_index
|
int
|
For star topology, the index of the hub agent. Defaults to 0. |
0
|
rounds
|
int
|
For mesh topology, number of communication rounds. |
1
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/structural/topology.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
pyagent_patterns.structural.blackboard.Blackboard
¶
Bases: Pattern
Shared-state communication via a blackboard store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agents
|
list[BlackboardAgent]
|
List of BlackboardAgent wrappers specifying read/write keys. |
required |
rounds
|
int
|
Number of rounds agents process the blackboard. |
1
|
initial_state
|
dict[str, Any] | None
|
Optional initial blackboard values. |
None
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/structural/blackboard.py
Advanced (Tier 4)¶
pyagent_patterns.advanced.talker_reasoner.TalkerReasoner
¶
Bases: Pattern
Dual-process: fast intuition (System 1) + slow deliberation (System 2).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
talker
|
Agent
|
Fast, cheap agent for routine queries (System 1). |
required |
reasoner
|
Agent
|
Slow, expensive agent for complex queries (System 2). |
required |
classifier
|
Agent | None
|
Optional agent that decides talker vs reasoner. If None, always starts with talker and escalates on uncertainty keywords. |
None
|
complexity_threshold
|
list[str] | None
|
Keywords in talker output that trigger escalation to reasoner. |
None
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/advanced/talker_reasoner.py
pyagent_patterns.advanced.swarm.Swarm
¶
Bases: Pattern
Decentralized swarm: agents interact locally, behavior emerges globally.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agents
|
list[Agent]
|
Pool of swarm agents (all follow same local rules). |
required |
rounds
|
int
|
Number of interaction rounds. |
3
|
neighbor_count
|
int
|
How many random peers each agent interacts with per round. |
2
|
aggregation
|
str
|
How to produce final output from swarm state. "last" = last round's outputs, "vote" = majority vote. |
'last'
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/advanced/swarm.py
pyagent_patterns.advanced.human_in_the_loop.HumanInTheLoop
¶
Bases: Pattern
Agent with human approval gate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
Agent
|
The LLM agent that processes the task. |
required |
review_fn
|
HumanReviewFn
|
Callable that presents output to human and returns decision. Signature: (output: str, metadata: dict) -> HumanDecision |
auto_approve
|
max_revisions
|
int
|
Maximum number of revision attempts after rejection. |
3
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/advanced/human_in_the_loop.py
pyagent_patterns.advanced.react.ReAct
¶
Bases: Pattern
Reasoning + Acting loop with tool use.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
Agent
|
The reasoning agent. |
required |
tools
|
dict[str, ToolFn] | None
|
Mapping of tool names to callable functions. |
None
|
max_steps
|
int
|
Maximum number of Thought→Action→Observation cycles. |
5
|
finish_token
|
str
|
Token in agent response that signals task completion. |
'FINISH'
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/advanced/react.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | |
Composite¶
pyagent_patterns.composite.CompositePattern
¶
Bases: Pattern
Chain multiple patterns with escalation on quality failure.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
patterns
|
list[Pattern]
|
Ordered list of patterns to try. |
required |
quality_check
|
QualityCheckFn
|
Function that evaluates whether a pattern's result is acceptable. If it returns False, the next pattern is tried. |
always_pass
|
combine_results
|
bool
|
If True, passes previous output as context to next pattern. |
True
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/composite.py
Recovery¶
pyagent_patterns.recovery.BoundedExecution
dataclass
¶
Wrap a pattern with resource limits.
Three-level recovery: 1. Retry with same pattern 2. Fallback to a cheaper/simpler pattern 3. Graceful degradation (return partial result)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pattern
|
Pattern
|
The primary pattern to execute. |
required |
fallback
|
Pattern | None
|
Optional simpler pattern to use on failure. |
None
|
max_retries
|
int
|
Maximum retry attempts before escalating. |
2
|
timeout_seconds
|
float
|
Maximum wall-clock time for the entire execution. |
300.0
|
max_tokens
|
int
|
Maximum total tokens before stopping. |
100000
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/recovery.py
run(task, context=None)
async
¶
Execute with bounded resources and three-level recovery.
Source code in packages/pyagent-patterns/src/pyagent_patterns/recovery.py
pyagent_patterns.recovery.CircuitBreaker
¶
Prevent cascading failures in multi-agent systems.
When a pattern fails repeatedly, the circuit opens and rejects requests immediately. After a reset timeout, it enters half-open state and allows one test request through.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
failure_threshold
|
int
|
Number of consecutive failures before opening. |
3
|
reset_timeout_seconds
|
float
|
Seconds before transitioning from open to half-open. |
60.0
|
fallback_result
|
str
|
Result to return when circuit is open. |
'[Circuit Open] Service temporarily unavailable.'
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/recovery.py
execute(pattern, task, context=None)
async
¶
Execute a pattern through the circuit breaker.
Source code in packages/pyagent-patterns/src/pyagent_patterns/recovery.py
Guardrails¶
pyagent_patterns.guardrails.GuardrailChain
¶
Chain multiple guardrails together. All must pass.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
guardrails
|
list[Guardrail]
|
List of guardrails to apply in order. |
required |
Source code in packages/pyagent-patterns/src/pyagent_patterns/guardrails.py
pyagent_patterns.guardrails.LengthGuard
¶
Bases: Guardrail
Reject messages exceeding a maximum length.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_chars
|
int
|
Maximum allowed characters. |
10000
|
truncate
|
bool
|
If True, truncate instead of rejecting. |
False
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/guardrails.py
pyagent_patterns.guardrails.PIIGuard
¶
Bases: Guardrail
Detect and optionally redact personally identifiable information.
Detects: email addresses, phone numbers, SSNs, credit card numbers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
redact
|
bool
|
If True, redact PII and pass. If False, reject on detection. |
True
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/guardrails.py
pyagent_patterns.guardrails.ContentGuard
¶
Bases: Guardrail
Block content matching configurable deny patterns.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
deny_patterns
|
list[str] | None
|
List of regex patterns that should be blocked. |
None
|
deny_words
|
list[str] | None
|
List of exact words/phrases to block. |
None
|
Source code in packages/pyagent-patterns/src/pyagent_patterns/guardrails.py
Advisor¶
pyagent_patterns.advisor.PatternAdvisor
¶
Recommend patterns based on task description and constraints.
Usage
advisor = PatternAdvisor() rec = advisor.recommend("Write and review code", Constraints(quality=Quality.HIGH)) print(rec.pattern, rec.reason)
Source code in packages/pyagent-patterns/src/pyagent_patterns/advisor.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | |
recommend(task, constraints=None)
¶
Recommend the best pattern for the given task and constraints.
Source code in packages/pyagent-patterns/src/pyagent_patterns/advisor.py
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | |