pop-framework 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. pop_framework-0.1.0/.claude/scheduled_tasks.lock +1 -0
  2. pop_framework-0.1.0/.claude/settings.local.json +7 -0
  3. pop_framework-0.1.0/.gitignore +32 -0
  4. pop_framework-0.1.0/.python-version +1 -0
  5. pop_framework-0.1.0/LICENSE +21 -0
  6. pop_framework-0.1.0/PKG-INFO +148 -0
  7. pop_framework-0.1.0/README.md +111 -0
  8. pop_framework-0.1.0/SKILLS.md +368 -0
  9. pop_framework-0.1.0/assets/logo.svg +23 -0
  10. pop_framework-0.1.0/benchmarks/bench_dx.py +121 -0
  11. pop_framework-0.1.0/benchmarks/bench_startup.py +329 -0
  12. pop_framework-0.1.0/benchmarks/results/dx_comparison.json +49 -0
  13. pop_framework-0.1.0/benchmarks/results/latest.json +34 -0
  14. pop_framework-0.1.0/benchmarks/results/latest_report.md +92 -0
  15. pop_framework-0.1.0/docs/benchmarks.md +46 -0
  16. pop_framework-0.1.0/docs/memory.md +56 -0
  17. pop_framework-0.1.0/docs/multi-agent.md +81 -0
  18. pop_framework-0.1.0/docs/providers.md +71 -0
  19. pop_framework-0.1.0/docs/streaming.md +46 -0
  20. pop_framework-0.1.0/docs/workflows.md +91 -0
  21. pop_framework-0.1.0/examples/01_hello_agent.py +37 -0
  22. pop_framework-0.1.0/examples/02_web_search_agent.py +64 -0
  23. pop_framework-0.1.0/examples/03_structured_output.py +56 -0
  24. pop_framework-0.1.0/examples/04_streaming.py +77 -0
  25. pop_framework-0.1.0/examples/05_multi_provider.py +54 -0
  26. pop_framework-0.1.0/examples/06_augmented_llm.py +103 -0
  27. pop_framework-0.1.0/examples/07_prompt_chaining.py +54 -0
  28. pop_framework-0.1.0/examples/08_routing.py +68 -0
  29. pop_framework-0.1.0/examples/09_parallelization.py +65 -0
  30. pop_framework-0.1.0/examples/10_orchestrator_workers.py +79 -0
  31. pop_framework-0.1.0/examples/11_evaluator_optimizer.py +72 -0
  32. pop_framework-0.1.0/pyproject.toml +104 -0
  33. pop_framework-0.1.0/src/pop/__init__.py +85 -0
  34. pop_framework-0.1.0/src/pop/_sync.py +32 -0
  35. pop_framework-0.1.0/src/pop/agent.py +328 -0
  36. pop_framework-0.1.0/src/pop/hooks/__init__.py +31 -0
  37. pop_framework-0.1.0/src/pop/hooks/base.py +66 -0
  38. pop_framework-0.1.0/src/pop/hooks/console.py +50 -0
  39. pop_framework-0.1.0/src/pop/hooks/cost.py +53 -0
  40. pop_framework-0.1.0/src/pop/hooks/file_log.py +46 -0
  41. pop_framework-0.1.0/src/pop/memory/__init__.py +24 -0
  42. pop_framework-0.1.0/src/pop/memory/base.py +38 -0
  43. pop_framework-0.1.0/src/pop/memory/inmemory.py +89 -0
  44. pop_framework-0.1.0/src/pop/memory/markdown.py +183 -0
  45. pop_framework-0.1.0/src/pop/models/__init__.py +43 -0
  46. pop_framework-0.1.0/src/pop/models/anthropic.py +228 -0
  47. pop_framework-0.1.0/src/pop/models/base.py +37 -0
  48. pop_framework-0.1.0/src/pop/models/deepseek.py +19 -0
  49. pop_framework-0.1.0/src/pop/models/gemini.py +222 -0
  50. pop_framework-0.1.0/src/pop/models/glm.py +19 -0
  51. pop_framework-0.1.0/src/pop/models/kimi.py +19 -0
  52. pop_framework-0.1.0/src/pop/models/minimax.py +19 -0
  53. pop_framework-0.1.0/src/pop/models/openai.py +187 -0
  54. pop_framework-0.1.0/src/pop/models/router.py +169 -0
  55. pop_framework-0.1.0/src/pop/multi/__init__.py +23 -0
  56. pop_framework-0.1.0/src/pop/multi/handoff.py +55 -0
  57. pop_framework-0.1.0/src/pop/multi/patterns.py +223 -0
  58. pop_framework-0.1.0/src/pop/py.typed +0 -0
  59. pop_framework-0.1.0/src/pop/runner.py +133 -0
  60. pop_framework-0.1.0/src/pop/tool.py +200 -0
  61. pop_framework-0.1.0/src/pop/types.py +314 -0
  62. pop_framework-0.1.0/src/pop/workflows/__init__.py +5 -0
  63. pop_framework-0.1.0/src/pop/workflows/patterns.py +103 -0
  64. pop_framework-0.1.0/tests/__init__.py +0 -0
  65. pop_framework-0.1.0/tests/conftest.py +52 -0
  66. pop_framework-0.1.0/tests/test_agent.py +892 -0
  67. pop_framework-0.1.0/tests/test_hooks.py +350 -0
  68. pop_framework-0.1.0/tests/test_memory/__init__.py +0 -0
  69. pop_framework-0.1.0/tests/test_memory/test_inmemory.py +110 -0
  70. pop_framework-0.1.0/tests/test_memory/test_markdown.py +279 -0
  71. pop_framework-0.1.0/tests/test_models/__init__.py +0 -0
  72. pop_framework-0.1.0/tests/test_models/test_anthropic.py +487 -0
  73. pop_framework-0.1.0/tests/test_models/test_deepseek.py +58 -0
  74. pop_framework-0.1.0/tests/test_models/test_gemini.py +479 -0
  75. pop_framework-0.1.0/tests/test_models/test_glm.py +58 -0
  76. pop_framework-0.1.0/tests/test_models/test_kimi.py +58 -0
  77. pop_framework-0.1.0/tests/test_models/test_minimax.py +66 -0
  78. pop_framework-0.1.0/tests/test_models/test_openai.py +516 -0
  79. pop_framework-0.1.0/tests/test_models/test_router.py +320 -0
  80. pop_framework-0.1.0/tests/test_multi/__init__.py +0 -0
  81. pop_framework-0.1.0/tests/test_multi/test_handoff.py +85 -0
  82. pop_framework-0.1.0/tests/test_multi/test_patterns.py +260 -0
  83. pop_framework-0.1.0/tests/test_runner.py +334 -0
  84. pop_framework-0.1.0/tests/test_sync.py +20 -0
  85. pop_framework-0.1.0/tests/test_tool.py +422 -0
  86. pop_framework-0.1.0/tests/test_types.py +127 -0
  87. pop_framework-0.1.0/tests/test_workflows/__init__.py +0 -0
  88. pop_framework-0.1.0/tests/test_workflows/test_patterns.py +227 -0
  89. pop_framework-0.1.0/uv.lock +1340 -0
@@ -0,0 +1 @@
1
+ {"sessionId":"8ece6f4d-7253-482f-a1fe-c9f20d8e45ae","pid":82460,"acquiredAt":1774307712777}
@@ -0,0 +1,7 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(python benchmarks/bench_startup.py)"
5
+ ]
6
+ }
7
+ }
@@ -0,0 +1,32 @@
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+
9
+ # Testing
10
+ .pytest_cache/
11
+ .coverage
12
+ htmlcov/
13
+
14
+ # Type checking & linting
15
+ .mypy_cache/
16
+ .ruff_cache/
17
+
18
+ # Environment
19
+ .env
20
+ .env.local
21
+ .venv/
22
+ venv/
23
+
24
+ # OS
25
+ .DS_Store
26
+ Thumbs.db
27
+
28
+ # IDE
29
+ .idea/
30
+ .vscode/
31
+ *.swp
32
+ *.swo
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Chester Lee
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,148 @@
1
+ Metadata-Version: 2.4
2
+ Name: pop-framework
3
+ Version: 0.1.0
4
+ Summary: Fast, lean AI agents. 5 lines to production.
5
+ Project-URL: Homepage, https://github.com/WYSIATI/pop
6
+ Project-URL: Documentation, https://github.com/WYSIATI/pop/tree/main/docs
7
+ Project-URL: Repository, https://github.com/WYSIATI/pop
8
+ Project-URL: Issues, https://github.com/WYSIATI/pop/issues
9
+ Author: Chester Lee
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: agents,ai,anthropic,framework,llm,openai
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: httpx>=0.27
25
+ Requires-Dist: pydantic>=2.0
26
+ Provides-Extra: all
27
+ Requires-Dist: anthropic>=0.30; extra == 'all'
28
+ Requires-Dist: google-genai>=1.0; extra == 'all'
29
+ Requires-Dist: openai>=1.0; extra == 'all'
30
+ Provides-Extra: anthropic
31
+ Requires-Dist: anthropic>=0.30; extra == 'anthropic'
32
+ Provides-Extra: gemini
33
+ Requires-Dist: google-genai>=1.0; extra == 'gemini'
34
+ Provides-Extra: openai
35
+ Requires-Dist: openai>=1.0; extra == 'openai'
36
+ Description-Content-Type: text/markdown
37
+
38
+ <p align="center">
39
+ <img src="assets/logo.svg" alt="pop" width="300">
40
+ </p>
41
+
42
+ <p align="center">
43
+ <em>Fast, lean AI agents. 5 lines to production.</em>
44
+ </p>
45
+
46
+ <p align="center">
47
+ <a href="https://github.com/WYSIATI/pop/actions"><img src="https://img.shields.io/github/actions/workflow/status/WYSIATI/pop/ci.yml?label=CI" alt="CI"></a>
48
+ <a href="https://github.com/WYSIATI/pop"><img src="https://img.shields.io/badge/coverage-99%25-brightgreen" alt="Coverage"></a>
49
+ <a href="https://pypi.org/project/pop-framework/"><img src="https://img.shields.io/pypi/v/pop-framework" alt="PyPI"></a>
50
+ <a href="https://pypi.org/project/pop-framework/"><img src="https://img.shields.io/pypi/pyversions/pop-framework" alt="Python"></a>
51
+ <img src="https://img.shields.io/badge/license-MIT-blue" alt="License">
52
+ </p>
53
+
54
+ <p align="center">
55
+ <a href="docs/">Documentation</a> |
56
+ <a href="https://github.com/WYSIATI/pop">Source Code</a> |
57
+ <a href="https://discord.gg/pop">Discord</a>
58
+ </p>
59
+
60
+ ---
61
+
62
+ **pop** is a lightweight Python framework for building AI agents. It supports multiple LLM providers, has 5 core concepts, and gets you from install to a working agent in under 2 minutes.
63
+
64
+ ## Why pop?
65
+
66
+ - **5 lines to a working agent** -- define a tool, create an agent, call `run`.
67
+ - **7 LLM providers built-in** -- OpenAI, Anthropic, Gemini, DeepSeek, Kimi, MiniMax, GLM. Switch by changing one string.
68
+ - **~2,500 lines of code** -- read the entire framework in an afternoon.
69
+ - **2 runtime dependencies** -- `httpx` and `pydantic`. Import time under 1ms (lazy imports).
70
+ - **Zero commercial dependencies** -- no forced telemetry, no vendor lock-in.
71
+
72
+ ## Install
73
+
74
+ ```bash
75
+ # Recommended
76
+ uv add pop-framework
77
+
78
+ # With a provider extra
79
+ uv add "pop-framework[openai]"
80
+ uv add "pop-framework[anthropic]"
81
+ uv add "pop-framework[all]"
82
+ ```
83
+
84
+ Or with pip:
85
+
86
+ ```bash
87
+ pip install pop-framework
88
+ pip install "pop-framework[openai]"
89
+ ```
90
+
91
+ ## Quick Start
92
+
93
+ ```python
94
+ from pop import Agent, tool
95
+
96
+ @tool
97
+ def search(query: str) -> str:
98
+ """Search the web for current information."""
99
+ return web_search(query) # your implementation
100
+
101
+ agent = Agent(model="openai:gpt-4o", tools=[search])
102
+ result = agent.run("What happened in AI today?")
103
+ print(result.output)
104
+ ```
105
+
106
+ That's it. No `StateGraph`, no `RunnableSequence`, no `ChannelWrite`.
107
+
108
+ ## Docs
109
+
110
+ | Guide | What it covers |
111
+ |-------|---------------|
112
+ | [Providers](docs/providers.md) | Switching LLMs, failover, model adapters |
113
+ | [Streaming](docs/streaming.md) | Real-time events, pattern matching |
114
+ | [Workflows](docs/workflows.md) | Chain, route, parallel, agent, orchestration |
115
+ | [Multi-Agent](docs/multi-agent.md) | Handoff, pipeline, debate, fan_out |
116
+ | [Memory](docs/memory.md) | In-memory and markdown-based persistence |
117
+ | [Skills](SKILLS.md) | Complete API guide for building agents |
118
+ | [Benchmarks](docs/benchmarks.md) | Performance numbers, framework comparison |
119
+
120
+ ## Benchmarks
121
+
122
+ | Metric | pop | LangChain + LangGraph | Delta |
123
+ |--------|-----|----------------------|-------|
124
+ | Framework overhead | ~0.15ms | ~45ms | ~300x faster |
125
+ | Import time | ~0.17ms | ~1,200ms | ~7,000x faster |
126
+ | Lines of code (avg task) | ~12 | ~42 | 71% less |
127
+ | Dependencies | 2 | 20+ | 90% fewer |
128
+
129
+ Details: [docs/benchmarks.md](docs/benchmarks.md)
130
+
131
+ ## Community
132
+
133
+ - [Discord](https://discord.gg/pop) -- questions, help, showcase
134
+ - [GitHub Issues](https://github.com/WYSIATI/pop/issues) -- bug reports
135
+ - [GitHub Discussions](https://github.com/WYSIATI/pop/discussions) -- feature ideas, Q&A
136
+
137
+ ## Contributing
138
+
139
+ ```bash
140
+ git clone https://github.com/WYSIATI/pop.git
141
+ cd pop
142
+ uv sync --group dev
143
+ uv run pytest
144
+ ```
145
+
146
+ ## License
147
+
148
+ MIT
@@ -0,0 +1,111 @@
1
+ <p align="center">
2
+ <img src="assets/logo.svg" alt="pop" width="300">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <em>Fast, lean AI agents. 5 lines to production.</em>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="https://github.com/WYSIATI/pop/actions"><img src="https://img.shields.io/github/actions/workflow/status/WYSIATI/pop/ci.yml?label=CI" alt="CI"></a>
11
+ <a href="https://github.com/WYSIATI/pop"><img src="https://img.shields.io/badge/coverage-99%25-brightgreen" alt="Coverage"></a>
12
+ <a href="https://pypi.org/project/pop-framework/"><img src="https://img.shields.io/pypi/v/pop-framework" alt="PyPI"></a>
13
+ <a href="https://pypi.org/project/pop-framework/"><img src="https://img.shields.io/pypi/pyversions/pop-framework" alt="Python"></a>
14
+ <img src="https://img.shields.io/badge/license-MIT-blue" alt="License">
15
+ </p>
16
+
17
+ <p align="center">
18
+ <a href="docs/">Documentation</a> |
19
+ <a href="https://github.com/WYSIATI/pop">Source Code</a> |
20
+ <a href="https://discord.gg/pop">Discord</a>
21
+ </p>
22
+
23
+ ---
24
+
25
+ **pop** is a lightweight Python framework for building AI agents. It supports multiple LLM providers, has 5 core concepts, and gets you from install to a working agent in under 2 minutes.
26
+
27
+ ## Why pop?
28
+
29
+ - **5 lines to a working agent** -- define a tool, create an agent, call `run`.
30
+ - **7 LLM providers built-in** -- OpenAI, Anthropic, Gemini, DeepSeek, Kimi, MiniMax, GLM. Switch by changing one string.
31
+ - **~2,500 lines of code** -- read the entire framework in an afternoon.
32
+ - **2 runtime dependencies** -- `httpx` and `pydantic`. Import time under 1ms (lazy imports).
33
+ - **Zero commercial dependencies** -- no forced telemetry, no vendor lock-in.
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ # Recommended
39
+ uv add pop-framework
40
+
41
+ # With a provider extra
42
+ uv add "pop-framework[openai]"
43
+ uv add "pop-framework[anthropic]"
44
+ uv add "pop-framework[all]"
45
+ ```
46
+
47
+ Or with pip:
48
+
49
+ ```bash
50
+ pip install pop-framework
51
+ pip install "pop-framework[openai]"
52
+ ```
53
+
54
+ ## Quick Start
55
+
56
+ ```python
57
+ from pop import Agent, tool
58
+
59
+ @tool
60
+ def search(query: str) -> str:
61
+ """Search the web for current information."""
62
+ return web_search(query) # your implementation
63
+
64
+ agent = Agent(model="openai:gpt-4o", tools=[search])
65
+ result = agent.run("What happened in AI today?")
66
+ print(result.output)
67
+ ```
68
+
69
+ That's it. No `StateGraph`, no `RunnableSequence`, no `ChannelWrite`.
70
+
71
+ ## Docs
72
+
73
+ | Guide | What it covers |
74
+ |-------|---------------|
75
+ | [Providers](docs/providers.md) | Switching LLMs, failover, model adapters |
76
+ | [Streaming](docs/streaming.md) | Real-time events, pattern matching |
77
+ | [Workflows](docs/workflows.md) | Chain, route, parallel, agent, orchestration |
78
+ | [Multi-Agent](docs/multi-agent.md) | Handoff, pipeline, debate, fan_out |
79
+ | [Memory](docs/memory.md) | In-memory and markdown-based persistence |
80
+ | [Skills](SKILLS.md) | Complete API guide for building agents |
81
+ | [Benchmarks](docs/benchmarks.md) | Performance numbers, framework comparison |
82
+
83
+ ## Benchmarks
84
+
85
+ | Metric | pop | LangChain + LangGraph | Delta |
86
+ |--------|-----|----------------------|-------|
87
+ | Framework overhead | ~0.15ms | ~45ms | ~300x faster |
88
+ | Import time | ~0.17ms | ~1,200ms | ~7,000x faster |
89
+ | Lines of code (avg task) | ~12 | ~42 | 71% less |
90
+ | Dependencies | 2 | 20+ | 90% fewer |
91
+
92
+ Details: [docs/benchmarks.md](docs/benchmarks.md)
93
+
94
+ ## Community
95
+
96
+ - [Discord](https://discord.gg/pop) -- questions, help, showcase
97
+ - [GitHub Issues](https://github.com/WYSIATI/pop/issues) -- bug reports
98
+ - [GitHub Discussions](https://github.com/WYSIATI/pop/discussions) -- feature ideas, Q&A
99
+
100
+ ## Contributing
101
+
102
+ ```bash
103
+ git clone https://github.com/WYSIATI/pop.git
104
+ cd pop
105
+ uv sync --group dev
106
+ uv run pytest
107
+ ```
108
+
109
+ ## License
110
+
111
+ MIT
@@ -0,0 +1,368 @@
1
+ # Skills Guide
2
+
3
+ How to build AI agents with pop. This guide is written for coding agents (Claude, Cursor, Copilot) and humans alike.
4
+
5
+ ## 5 Core Concepts
6
+
7
+ | Concept | What it does |
8
+ |---------|-------------|
9
+ | `Agent` | ReAct loop: thinks, calls tools, repeats until done |
10
+ | `@tool` | Turns a Python function into a tool the LLM can call |
11
+ | `Runner` | Streams events from an agent run |
12
+ | Memory | Pluggable storage (in-memory or markdown files) |
13
+ | Patterns | Multi-agent composition: `handoff`, `pipeline`, `debate`, `orchestrate`, `fan_out` |
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ uv add pop-framework
19
+ # With a provider
20
+ uv add "pop-framework[openai]"
21
+ uv add "pop-framework[anthropic]"
22
+ ```
23
+
24
+ ## 1. Minimal Agent
25
+
26
+ ```python
27
+ from pop import Agent, tool
28
+
29
+ @tool
30
+ def add(a: float, b: float) -> float:
31
+ """Add two numbers.
32
+
33
+ Args:
34
+ a: First number.
35
+ b: Second number.
36
+ """
37
+ return a + b
38
+
39
+ agent = Agent(model="openai:gpt-4o-mini", tools=[add])
40
+ result = agent.run("What is 42 + 17?")
41
+ print(result.output)
42
+ ```
43
+
44
+ **Key points:**
45
+ - `@tool` reads the function signature and docstring to generate JSON Schema automatically
46
+ - Use Google-style docstrings with `Args:` section for parameter descriptions
47
+ - `model` is a string in `provider:model-name` format
48
+
49
+ ## 2. Defining Tools
50
+
51
+ ```python
52
+ from pop import tool
53
+
54
+ # Simple tool
55
+ @tool
56
+ def search(query: str) -> str:
57
+ """Search the web."""
58
+ return f"Results for {query}"
59
+
60
+ # Tool with optional params
61
+ @tool
62
+ def fetch_page(url: str, max_length: int = 5000) -> str:
63
+ """Fetch a web page.
64
+
65
+ Args:
66
+ url: The URL to fetch.
67
+ max_length: Max characters to return.
68
+ """
69
+ return httpx.get(url).text[:max_length]
70
+
71
+ # Tool with Pydantic input
72
+ from pydantic import BaseModel, Field
73
+
74
+ class Contact(BaseModel):
75
+ name: str = Field(description="Full name")
76
+ email: str = Field(description="Email address")
77
+
78
+ @tool
79
+ def save_contact(contact: Contact) -> str:
80
+ """Save a contact to the database.
81
+
82
+ Args:
83
+ contact: Contact information.
84
+ """
85
+ return f"Saved {contact.name}"
86
+ ```
87
+
88
+ **Supported types:** `str`, `int`, `float`, `bool`, `list[T]`, `dict`, Pydantic models, `Optional[T]`.
89
+
90
+ ## 3. Agent Configuration
91
+
92
+ ```python
93
+ agent = Agent(
94
+ model="openai:gpt-4o", # or "anthropic:claude-sonnet-4-20250514"
95
+ name="researcher", # name for multi-agent identification
96
+ tools=[search, fetch_page], # list of @tool-decorated functions
97
+ instructions="You are a research assistant. Cite sources.",
98
+ max_steps=10, # max ReAct loop iterations (default: 10)
99
+ max_cost=0.50, # USD budget cap (optional)
100
+ max_retries=3, # retries on transient errors
101
+ reflect_on_failure=False, # enable Reflexion loop on errors
102
+ output_guardrails=[is_safe], # validators for final answer
103
+ )
104
+ ```
105
+
106
+ **Model fallback:** pass a list to try models in order.
107
+
108
+ ```python
109
+ agent = Agent(
110
+ model=["anthropic:claude-sonnet-4-20250514", "openai:gpt-4o", "openai:gpt-4o-mini"],
111
+ tools=[search],
112
+ )
113
+ ```
114
+
115
+ ## 4. Running Agents
116
+
117
+ ### Sync
118
+
119
+ ```python
120
+ result = agent.run("What happened in AI today?")
121
+ print(result.output) # final answer string
122
+ print(result.cost) # total USD cost
123
+ print(result.token_usage) # TokenUsage(input_tokens=..., output_tokens=...)
124
+ print(result.steps) # list[Step] -- full execution trace
125
+ ```
126
+
127
+ ### Async
128
+
129
+ ```python
130
+ result = await agent.arun("What happened in AI today?")
131
+ ```
132
+
133
+ ### Streaming
134
+
135
+ ```python
136
+ import asyncio
137
+ from pop import Agent, Runner, ToolCallEvent, ToolResultEvent, TextDeltaEvent, DoneEvent, tool
138
+
139
+ runner = Runner(agent)
140
+
141
+ async for event in runner.stream("What should I wear in SF?"):
142
+ match event:
143
+ case ToolCallEvent(name=name, args=args):
144
+ print(f"Calling {name}({args})")
145
+ case ToolResultEvent(name=name, output=output):
146
+ print(f"{name} -> {output}")
147
+ case TextDeltaEvent(delta=text):
148
+ print(text, end="")
149
+ case DoneEvent(result=result):
150
+ print(f"\nCost: ${result.cost:.6f}")
151
+ ```
152
+
153
+ ## 5. Multi-Agent Patterns
154
+
155
+ ### Handoff
156
+
157
+ Route to specialist agents based on the task.
158
+
159
+ ```python
160
+ from pop import Agent, handoff, tool
161
+
162
+ billing = Agent(model="openai:gpt-4o-mini", tools=[lookup_invoice],
163
+ instructions="Handle billing questions.")
164
+ tech = Agent(model="openai:gpt-4o-mini", tools=[check_logs],
165
+ instructions="Handle technical issues.")
166
+
167
+ triage = Agent(
168
+ model="openai:gpt-4o-mini",
169
+ tools=[
170
+ handoff(billing, when="billing or payment issues"),
171
+ handoff(tech, when="technical problems or errors"),
172
+ ],
173
+ )
174
+ result = triage.run("I was charged twice")
175
+ ```
176
+
177
+ ### Pipeline
178
+
179
+ Sequential: each agent's output feeds into the next.
180
+
181
+ ```python
182
+ from pop import Agent, pipeline
183
+
184
+ result = await pipeline(
185
+ [researcher, writer, editor],
186
+ task="Report on AI agent frameworks",
187
+ )
188
+ ```
189
+
190
+ ### Debate
191
+
192
+ Generator proposes, critic reviews, loop until approved.
193
+
194
+ ```python
195
+ from pop import Agent, debate
196
+
197
+ result = await debate(writer, editor, task="Write a product announcement", max_rounds=3)
198
+ ```
199
+
200
+ ### Orchestrate
201
+
202
+ A boss agent dynamically delegates to workers.
203
+
204
+ ```python
205
+ from pop import Agent, orchestrate
206
+
207
+ boss = Agent(model="openai:gpt-4o", name="boss",
208
+ instructions="Coordinate research, writing, and SEO.")
209
+ result = await orchestrate(boss, [researcher, writer, seo_optimizer], task="Write a blog post")
210
+ ```
211
+
212
+ ### Fan Out
213
+
214
+ Run multiple agents in parallel, aggregate results.
215
+
216
+ ```python
217
+ from pop import Agent, fan_out
218
+
219
+ result = await fan_out(
220
+ [analyst_a, analyst_b, analyst_c],
221
+ task="Analyze Q4 earnings",
222
+ strategy="majority", # or "first", "weighted_vote"
223
+ )
224
+ ```
225
+
226
+ ## 6. Workflows (No Agent Loop)
227
+
228
+ For simpler LLM patterns that don't need tool-calling or a ReAct loop.
229
+
230
+ ```python
231
+ from pop import chain, route, parallel, model
232
+
233
+ m = model("openai:gpt-4o")
234
+
235
+ # Chain: sequential prompts, {prev} is replaced with the previous output
236
+ result = await chain(m, steps=[
237
+ "Summarize: {input}",
238
+ "Translate to French: {prev}",
239
+ ], input_text="...")
240
+
241
+ # Route: classify and dispatch
242
+ result = await route(m, "refund request", {
243
+ "refund": handle_refund,
244
+ "support": handle_support,
245
+ })
246
+
247
+ # Parallel: concurrent LLM calls
248
+ results = await parallel(m, [
249
+ "Summarize: {context}",
250
+ "Extract keywords: {context}",
251
+ ], context="...")
252
+ ```
253
+
254
+ ## 7. Memory
255
+
256
+ ### In-Memory (Default)
257
+
258
+ No configuration needed. State is lost when the process exits.
259
+
260
+ ### Markdown Memory (Persistent)
261
+
262
+ ```python
263
+ from pop.memory import MarkdownMemory
264
+
265
+ # Default: stores in ~/.pop/memory
266
+ memory = MarkdownMemory()
267
+
268
+ # Or specify a custom directory
269
+ memory = MarkdownMemory(base_dir="./agent_memory")
270
+
271
+ agent = Agent(
272
+ model="openai:gpt-4o",
273
+ tools=[search],
274
+ memory=memory,
275
+ core_memory={
276
+ "user_name": "Chester",
277
+ "preferences": "Concise answers. No fluff.",
278
+ },
279
+ )
280
+ ```
281
+
282
+ Default directory: `~/.pop/memory`. Override with `POP_MEMORY_DIR` env var or the `base_dir` argument.
283
+
284
+ Core memory (`dict[str, str]`) is always included in context. Episodes and conversations persist as markdown files on disk.
285
+
286
+ ## 8. Hooks
287
+
288
+ ```python
289
+ from pop.hooks import ConsoleHook, CostHook, FileLogHook
290
+
291
+ runner = Runner(agent, hooks=[
292
+ ConsoleHook(), # print steps to stdout
293
+ CostHook(budget=1.00), # track cumulative cost
294
+ FileLogHook(path="./agent.log"), # append steps to JSON file
295
+ ])
296
+ ```
297
+
298
+ ## 9. Providers
299
+
300
+ 7 built-in: OpenAI, Anthropic, Gemini, DeepSeek, Kimi, MiniMax, GLM.
301
+
302
+ ```python
303
+ # Switch by changing the string
304
+ Agent(model="openai:gpt-4o")
305
+ Agent(model="anthropic:claude-sonnet-4-20250514")
306
+ Agent(model="gemini:gemini-2.0-flash")
307
+ Agent(model="deepseek:deepseek-chat")
308
+ ```
309
+
310
+ Custom providers implement `ModelAdapter`:
311
+
312
+ ```python
313
+ from pop.models import ModelAdapter, register_provider
314
+
315
+ class MyAdapter(ModelAdapter):
316
+ async def chat(self, messages, tools=None):
317
+ ... # return ModelResponse
318
+
319
+ async def chat_stream(self, messages, tools=None):
320
+ ... # yield StreamChunk
321
+
322
+ register_provider("my_provider", MyAdapter)
323
+ Agent(model="my_provider:my-model")
324
+ ```
325
+
326
+ ## 10. Inspecting Results
327
+
328
+ Every run returns `AgentResult` with a full trace:
329
+
330
+ ```python
331
+ result = agent.run("...")
332
+
333
+ # Walk the step trace
334
+ for step in result.steps:
335
+ print(f"Step {step.index}: {step.tool_name or 'final answer'}")
336
+ if step.tool_name:
337
+ print(f" Args: {step.tool_args}")
338
+ print(f" Result: {step.tool_result}")
339
+ print(f" Tokens: {step.token_usage.total}")
340
+ print(f" Cost: ${step.cost_usd:.6f}")
341
+
342
+ # Totals
343
+ print(f"Total cost: ${result.cost:.6f}")
344
+ print(f"Total tokens: {result.token_usage.total}")
345
+ print(f"Run ID: {result.run_id}")
346
+ ```
347
+
348
+ ## Quick Reference
349
+
350
+ ```python
351
+ from pop import (
352
+ # Core
353
+ Agent, tool, Runner, run,
354
+ # Multi-agent
355
+ handoff, pipeline, orchestrate, debate, fan_out,
356
+ # Workflows
357
+ chain, route, parallel,
358
+ # Models
359
+ chat, model, register_provider,
360
+ # Types
361
+ AgentResult, Step, TokenUsage, Message,
362
+ # Stream events
363
+ ThinkEvent, ToolCallEvent, ToolResultEvent, TextDeltaEvent, DoneEvent,
364
+ )
365
+
366
+ from pop.memory import MarkdownMemory, InMemoryStore
367
+ from pop.hooks import ConsoleHook, CostHook, FileLogHook
368
+ ```