ni.agentkit 0.6.2__tar.gz → 0.7.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 (118) hide show
  1. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/PKG-INFO +3 -3
  2. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/README.md +2 -2
  3. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/__init__.py +1 -1
  4. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/docs/Architecture.md +10 -2
  5. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/docs/QuickStart.md +109 -24
  6. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/docs/README.md +3 -2
  7. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/docs/Reference.md +45 -0
  8. ni_agentkit-0.7.0/docs/TestReport.md +92 -0
  9. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/01_basic_chat.py +10 -9
  10. ni_agentkit-0.7.0/examples/ollama/05_human_in_the_loop.py +42 -0
  11. ni_agentkit-0.7.0/examples/ollama/08a_memory_simple_provider.py +59 -0
  12. ni_agentkit-0.7.0/examples/ollama/08b_memory_mem0_provider.py +57 -0
  13. ni_agentkit-0.7.0/examples/ollama/08c_memory_file_provider.py +102 -0
  14. ni_agentkit-0.7.0/examples/ollama/09c_nebula_graph_tool.py +76 -0
  15. ni_agentkit-0.7.0/examples/ollama/19_hitl_deterministic.py +57 -0
  16. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/README.md +1 -0
  17. ni_agentkit-0.7.0/examples/standard/08a_memory_simple_provider.py +59 -0
  18. ni_agentkit-0.7.0/examples/standard/08b_memory_mem0_provider.py +49 -0
  19. ni_agentkit-0.7.0/examples/standard/08c_memory_file_provider.py +102 -0
  20. ni_agentkit-0.7.0/examples/standard/09c_nebula_graph_tool.py +72 -0
  21. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/README.md +1 -0
  22. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/ni.agentkit.egg-info/PKG-INFO +3 -3
  23. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/ni.agentkit.egg-info/SOURCES.txt +21 -0
  24. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/pyproject.toml +1 -1
  25. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/runner/events.py +32 -2
  26. ni_agentkit-0.7.0/tests/test_graph_repository.py +83 -0
  27. ni_agentkit-0.6.2/docs/TestReport.md +0 -80
  28. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/LICENSE +0 -0
  29. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/_cli.py +0 -0
  30. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/agents/__init__.py +0 -0
  31. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/agents/agent.py +0 -0
  32. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/agents/base_agent.py +0 -0
  33. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/agents/orchestrators.py +0 -0
  34. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/__init__.py +0 -0
  35. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/02_tool_calling.py +0 -0
  36. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/03_skill_usage.py +0 -0
  37. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/04_multi_agent.py +0 -0
  38. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/05_guardrail.py +0 -0
  39. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/06_orchestration.py +0 -0
  40. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/07_sync_async_stream.py +0 -0
  41. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/08_memory.py +0 -0
  42. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/09a_structured_data_sql.py +0 -0
  43. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/09b_structured_data_graph.py +0 -0
  44. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/10_skill_lifecycle.py +0 -0
  45. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/11_orchestration_enhancement.py +0 -0
  46. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/12_run_context_serialization.py +0 -0
  47. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/13_human_in_the_loop.py +0 -0
  48. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/14_event_standardization.py +0 -0
  49. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/15_multi_tenant_isolation.py +0 -0
  50. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/16_lifecycle_hooks.py +0 -0
  51. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/17_checkpoint_handoff_resume.py +0 -0
  52. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/18_model_cosplay.py +0 -0
  53. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/__init__.py +0 -0
  54. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/quickstart.py +0 -0
  55. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/01_basic_chat.py +0 -0
  56. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/02_tool_calling.py +0 -0
  57. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/03_skill_usage.py +0 -0
  58. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/04_multi_agent.py +0 -0
  59. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/05_guardrail.py +0 -0
  60. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/06_orchestration.py +0 -0
  61. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/07_sync_async_stream.py +0 -0
  62. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/08_memory.py +0 -0
  63. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/09a_structured_data_sql.py +0 -0
  64. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/09b_structured_data_graph.py +0 -0
  65. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/10_skill_lifecycle.py +0 -0
  66. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/11_orchestration_enhancement.py +0 -0
  67. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/12_run_context_serialization.py +0 -0
  68. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/13_human_in_the_loop.py +0 -0
  69. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/14_event_standardization.py +0 -0
  70. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/15_multi_tenant_isolation.py +0 -0
  71. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/16_lifecycle_hooks.py +0 -0
  72. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/17_checkpoint_handoff_resume.py +0 -0
  73. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/18_model_cosplay.py +0 -0
  74. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/__init__.py +0 -0
  75. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/test_ollama.py +0 -0
  76. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/__init__.py +0 -0
  77. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/adapters/__init__.py +0 -0
  78. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/adapters/anthropic_adapter.py +0 -0
  79. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/adapters/google_adapter.py +0 -0
  80. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/adapters/ollama_adapter.py +0 -0
  81. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/adapters/openai_adapter.py +0 -0
  82. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/adapters/openai_compatible.py +0 -0
  83. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/base.py +0 -0
  84. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/cache.py +0 -0
  85. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/middleware.py +0 -0
  86. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/registry.py +0 -0
  87. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/types.py +0 -0
  88. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/memory/__init__.py +0 -0
  89. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/memory/base.py +0 -0
  90. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/memory/mem0_provider.py +0 -0
  91. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/ni.agentkit.egg-info/dependency_links.txt +0 -0
  92. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/ni.agentkit.egg-info/entry_points.txt +0 -0
  93. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/ni.agentkit.egg-info/requires.txt +0 -0
  94. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/ni.agentkit.egg-info/top_level.txt +0 -0
  95. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/runner/__init__.py +0 -0
  96. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/runner/context.py +0 -0
  97. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/runner/context_store.py +0 -0
  98. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/runner/runner.py +0 -0
  99. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/safety/__init__.py +0 -0
  100. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/safety/guardrails.py +0 -0
  101. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/safety/permissions.py +0 -0
  102. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/setup.cfg +0 -0
  103. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/skills/__init__.py +0 -0
  104. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/skills/loader.py +0 -0
  105. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/skills/models.py +0 -0
  106. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/skills/registry.py +0 -0
  107. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tests/test_after_callback.py +0 -0
  108. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tests/test_quickstart_core.py +0 -0
  109. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tests/test_runner_checkpoint_resume.py +0 -0
  110. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/__init__.py +0 -0
  111. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/base_tool.py +0 -0
  112. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/function_tool.py +0 -0
  113. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/nebula_tool.py +0 -0
  114. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/skill_toolset.py +0 -0
  115. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/sqlite_tool.py +0 -0
  116. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/structured_data.py +0 -0
  117. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/utils/__init__.py +0 -0
  118. {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/utils/schema.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ni.agentkit
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: A Python-native Agent framework with first-class Skill support and multi-LLM adapter
5
5
  Author-email: Krix Tam <krix.tam@qq.com>
6
6
  License: MIT
@@ -153,8 +153,8 @@ python "$(python -c "import agentkit, os; print(os.path.join(agentkit.get_exampl
153
153
 
154
154
  ```bash
155
155
  dist/
156
- ├── ni_agentkit-0.6.2-py3-none-any.whl # pip install 用这个
157
- └── ni_agentkit-0.6.2.tar.gz # 源码分发
156
+ ├── ni_agentkit-0.7.0-py3-none-any.whl # pip install 用这个
157
+ └── ni_agentkit-0.7.0.tar.gz # 源码分发
158
158
  ```
159
159
 
160
160
  ## 📄 License
@@ -111,8 +111,8 @@ python "$(python -c "import agentkit, os; print(os.path.join(agentkit.get_exampl
111
111
 
112
112
  ```bash
113
113
  dist/
114
- ├── ni_agentkit-0.6.2-py3-none-any.whl # pip install 用这个
115
- └── ni_agentkit-0.6.2.tar.gz # 源码分发
114
+ ├── ni_agentkit-0.7.0-py3-none-any.whl # pip install 用这个
115
+ └── ni_agentkit-0.7.0.tar.gz # 源码分发
116
116
  ```
117
117
 
118
118
  ## 📄 License
@@ -31,7 +31,7 @@ from .tools.function_tool import FunctionTool, function_tool
31
31
  from .tools.structured_data import ResultFormatter, StructuredDataTool
32
32
  from .tools.sqlite_tool import SQLiteTool, SQLiteResultFormatter
33
33
 
34
- __version__ = "0.6.2"
34
+ __version__ = "0.7.0"
35
35
 
36
36
 
37
37
  def get_docs_dir() -> str:
@@ -575,6 +575,14 @@ agentkit/
575
575
  │ ├── structured_data.py # StructuredDataTool / ResultFormatter
576
576
  │ ├── sqlite_tool.py # SQLiteTool
577
577
  │ ├── nebula_tool.py # NebulaGraphTool
578
+ │ ├── graph/ # 统一图接口层(Adapter/Repository/Tool)
579
+ │ │ ├── protocols.py # GraphAdapter 协议
580
+ │ │ ├── repository.py # GraphRepository(统一访问入口)
581
+ │ │ ├── factory.py # create_graph_repository* 工厂
582
+ │ │ ├── networkx_adapter.py
583
+ │ │ ├── litegraph_adapter.py
584
+ │ │ ├── nebula_adapter.py
585
+ │ │ └── tool.py # GraphQueryTool
578
586
  │ └── skill_toolset.py # SkillToolset(4 个桥接工具)
579
587
 
580
588
  ├── skills/ # Skill 层
@@ -612,8 +620,8 @@ agentkit/
612
620
  │ └── schema.py # 函数签名 → JSON Schema
613
621
 
614
622
  ├── examples/ # 示例
615
- │ ├── standard/ # 标准版示例(01-18,含 9A/9B)
616
- │ ├── ollama/ # Ollama 版示例(01-18,含 9A/9B)
623
+ │ ├── standard/ # 标准版示例(01-18,含 8A/8B/8C、9A/9B/9C
624
+ │ ├── ollama/ # Ollama 版示例(01-19,含 8A/8B/8C、9A/9B/9C
617
625
  │ ├── quickstart.py
618
626
  │ └── test_ollama.py
619
627
 
@@ -1,6 +1,6 @@
1
1
  # AgentKit 快速入门教程
2
2
 
3
- > 本教程将带你从零开始,通过 18 组由简到繁的示例(含 9A/9B),掌握 AgentKit 的核心用法。
3
+ > 本教程将带你从零开始,通过 18 组由简到繁的示例(含 8A/8B/8C、9A/9B/9C),掌握 AgentKit 的核心用法。
4
4
 
5
5
  ---
6
6
 
@@ -21,6 +21,7 @@
21
21
  - [示例 8:记忆系统 — 跨会话长期记忆](#示例-8记忆系统--跨会话长期记忆)
22
22
  - [示例 9A:关系型数据库 — 防止 SQL 注入的参数化 Tool](#示例-9a关系型数据库--防止-sql-注入的参数化-tool)
23
23
  - [示例 9B:图数据库 — 配合 Mock 运行的 NebulaGraphTool](#示例-9b图数据库--配合-mock-运行的-nebulagraphtool)
24
+ - [示例 9C:NebulaGraphTool 最小可执行示例(工具层直调)](#示例-9cnebulagraphtool-最小可执行示例工具层直调)
24
25
  - [示例 10:Skill 生命周期 — 管理外部资源连接池](#示例-10skill-生命周期--管理外部资源连接池)
25
26
  - [示例 11:编排增强 — 循环退出条件与并行提前终止](#示例-11编排增强--循环退出条件与并行提前终止)
26
27
  - [示例 12:RunContext 序列化与共享状态](#示例-12runcontext-序列化与共享状态)
@@ -608,60 +609,45 @@ asyncio.run(stream_demo())
608
609
 
609
610
  默认情况下,Agent 每次运行都是无状态的。配上记忆后,Agent 可以记住用户的偏好和历史。
610
611
 
611
- ### 无需外部依赖的 SimpleMemory
612
+ ### 8A:SimpleMemory
612
613
 
613
614
  ```python
614
615
  from agentkit import Agent, Runner, BaseMemoryProvider, Memory
615
616
 
616
617
  class SimpleMemory(BaseMemoryProvider):
617
- """轻量内存记忆——适合开发测试"""
618
618
  def __init__(self):
619
619
  self._store, self._counter = [], 0
620
-
621
620
  async def add(self, content, *, user_id=None, agent_id=None, metadata=None):
622
621
  self._counter += 1
623
622
  m = Memory(id=str(self._counter), content=content)
624
623
  self._store.append(m)
625
624
  return [m]
626
-
627
625
  async def search(self, query, *, user_id=None, agent_id=None, limit=10):
628
- # 简单关键词匹配(生产环境用 Mem0 的向量搜索)
629
626
  query_words = set(query)
630
627
  scored = [(len(query_words & set(m.content)), m) for m in self._store]
631
628
  scored.sort(reverse=True, key=lambda x: x[0])
632
629
  return [m for s, m in scored[:limit] if s > 0]
633
-
634
630
  async def get_all(self, *, user_id=None, agent_id=None):
635
631
  return list(self._store)
636
-
637
632
  async def delete(self, memory_id):
638
633
  self._store = [m for m in self._store if m.id != memory_id]
639
634
  return True
640
635
 
641
- # 给 Agent 配上记忆
642
636
  memory = SimpleMemory()
643
-
644
637
  agent = Agent(
645
638
  name="personal-assistant",
646
639
  instructions="你是一个贴心的个人助手。根据记忆来个性化回答。",
647
640
  model="ollama/qwen3.5:cloud",
648
- memory=memory, # ← 加上这一行
641
+ memory=memory,
642
+ memory_async_write=False,
649
643
  )
650
644
 
651
- # 第 1 轮:告诉偏好
652
645
  Runner.run_sync(agent, input="我叫小明,我喜欢喝咖啡,讨厌喝茶", user_id="krix")
653
-
654
- # 第 2 轮:Agent 会记住偏好,推荐咖啡而不是茶
655
646
  result = Runner.run_sync(agent, input="帮我推荐一杯饮料", user_id="krix")
656
- print(result.final_output) # "推荐拿铁!" — 基于记忆推荐
647
+ print(result.final_output) # 基于记忆推荐
657
648
  ```
658
649
 
659
- **要点**:
660
- - 默认不开启记忆,需要给 `Agent` 传 `memory=...` 参数
661
- - 配好后**不需要写额外代码**——框架自动在对话前检索记忆、对话后存储记忆
662
- - `user_id` 用于多用户隔离
663
-
664
- ### 生产环境使用 Mem0
650
+ ### 8B:Mem0Provider(生产级)
665
651
 
666
652
  ```bash
667
653
  pip install mem0ai
@@ -678,11 +664,47 @@ memory = Mem0Provider({
678
664
  }
679
665
  })
680
666
 
681
- agent = Agent(memory=memory, ...) # 替换 SimpleMemory 即可
667
+ agent = Agent(memory=memory, ...) # 先构建 memory,再注入 Agent
682
668
  ```
683
669
 
684
670
  Mem0 相比 SimpleMemory 的优势:**语义搜索**(理解意思而非关键词)、**持久化**(重启不丢失)、**智能提取**(从对话中自动抽取关键信息)。
685
671
 
672
+ ### 8C:自定义 Memory(文件持久化)
673
+
674
+ ```python
675
+ import json
676
+ from pathlib import Path
677
+ from agentkit import BaseMemoryProvider, Memory, Agent
678
+
679
+ class FileMemoryProvider(BaseMemoryProvider):
680
+ def __init__(self, file_path: str):
681
+ self.path = Path(file_path)
682
+ self.records = json.loads(self.path.read_text()) if self.path.exists() else []
683
+ async def add(self, content, *, user_id=None, agent_id=None, metadata=None):
684
+ new_id = str(len(self.records) + 1)
685
+ self.records.append({"id": new_id, "content": content, "user_id": user_id})
686
+ self.path.write_text(json.dumps(self.records, ensure_ascii=False, indent=2))
687
+ return [Memory(id=new_id, content=content)]
688
+ async def search(self, query, *, user_id=None, agent_id=None, limit=10):
689
+ q = query.lower()
690
+ out = [r for r in self.records if q in r["content"].lower()]
691
+ return [Memory(id=r["id"], content=r["content"]) for r in out[:limit]]
692
+ async def get_all(self, *, user_id=None, agent_id=None):
693
+ return [Memory(id=r["id"], content=r["content"]) for r in self.records]
694
+ async def delete(self, memory_id):
695
+ self.records = [r for r in self.records if r["id"] != memory_id]
696
+ self.path.write_text(json.dumps(self.records, ensure_ascii=False, indent=2))
697
+ return True
698
+
699
+ memory = FileMemoryProvider("/tmp/agentkit_memory.json")
700
+ agent = Agent(memory=memory, ...)
701
+ ```
702
+
703
+ **要点**:
704
+ - 默认不开启记忆,需要给 `Agent` 传 `memory=...` 参数
705
+ - `SimpleMemory` 适合开发测试,`Mem0Provider` 适合生产语义检索
706
+ - 自定义 `FileMemoryProvider` 可实现轻量持久化(进程重启后仍可读取)
707
+
686
708
  ---
687
709
 
688
710
  ## 示例 9A:关系型数据库 — 防止 SQL 注入的参数化 Tool
@@ -803,6 +825,63 @@ if __name__ == "__main__":
803
825
 
804
826
  ---
805
827
 
828
+ ## 示例 9C:NebulaGraphTool 最小可执行示例(工具层直调)
829
+
830
+ 如果你想先验证 `NebulaGraphTool` 本身(参数校验、查询模板拼接、formatter 输出)是否工作正常,可以不经过 LLM,直接调用工具执行。
831
+
832
+ ```python
833
+ import asyncio
834
+ from typing import Any
835
+ from pydantic import BaseModel, Field
836
+ from agentkit.runner.context import RunContext
837
+ from agentkit.tools.nebula_tool import NebulaGraphTool
838
+ from agentkit.tools.structured_data import ResultFormatter
839
+
840
+ class MockSession:
841
+ def execute(self, query: str):
842
+ print(f"[MockSession] execute gql => {query}")
843
+ return "mock_result_set"
844
+ def release(self): pass
845
+
846
+ class MockConnectionPool:
847
+ def get_session(self, user, password):
848
+ return MockSession()
849
+
850
+ class MockNebulaFormatter(ResultFormatter):
851
+ def format(self, raw_result: Any) -> Any:
852
+ return {"summary": "Query succeeded (mock)", "data": [{"friend_name": "Bob"}]}
853
+
854
+ class PersonQueryArgs(BaseModel):
855
+ name: str = Field(..., pattern=r"^[A-Za-z0-9_]+$")
856
+
857
+ nebula_tool = NebulaGraphTool(
858
+ name="find_person_friends",
859
+ description="查询某个人在图谱中的朋友关系",
860
+ parameters_schema=PersonQueryArgs,
861
+ query_template='MATCH (v:person)-[:friend]->(e:person) WHERE id(v) == "{name}" RETURN e.name AS friend_name;',
862
+ space_name="social_graph",
863
+ connection_pool=MockConnectionPool(),
864
+ formatter=MockNebulaFormatter(),
865
+ )
866
+
867
+ async def main():
868
+ payload = await nebula_tool.execute(RunContext(input="demo"), {"name": "Alice_001"})
869
+ print(payload)
870
+
871
+ if __name__ == "__main__":
872
+ asyncio.run(main())
873
+ ```
874
+
875
+ 运行文件:
876
+ - `examples/standard/09c_nebula_graph_tool.py`
877
+ - `examples/ollama/09c_nebula_graph_tool.py`
878
+
879
+ **要点**:
880
+ - 该示例不依赖真实 Nebula 集群,也不依赖 LLM,可用于本地快速验证 Tool 行为。
881
+ - 后续接入真实 Nebula 时,只需替换 `connection_pool` 与(可选)`formatter`。
882
+
883
+ ---
884
+
806
885
  ## 示例 10:Skill 生命周期 — 管理外部资源连接池
807
886
 
808
887
  当 Skill 依赖外部资源(如数据库连接池、长期会话句柄)时,你需要确保在使用前正确初始化,并在结束时安全释放。
@@ -1159,9 +1238,12 @@ agent = Agent(name="assistant", instructions="...")
1159
1238
  | [`05_guardrail.py`](../examples/standard/05_guardrail.py) | 示例 5:安全护栏 |
1160
1239
  | [`06_orchestration.py`](../examples/standard/06_orchestration.py) | 示例 6:编排 Agent |
1161
1240
  | [`07_sync_async_stream.py`](../examples/standard/07_sync_async_stream.py) | 示例 7:同步/异步/流式运行 |
1162
- | [`08_memory.py`](../examples/standard/08_memory.py) | 示例 8:记忆系统 |
1241
+ | [`08a_memory_simple_provider.py`](../examples/standard/08a_memory_simple_provider.py) | 示例 8A:记忆系统(SimpleMemory) |
1242
+ | [`08b_memory_mem0_provider.py`](../examples/standard/08b_memory_mem0_provider.py) | 示例 8B:记忆系统(Mem0Provider) |
1243
+ | [`08c_memory_file_provider.py`](../examples/standard/08c_memory_file_provider.py) | 示例 8C:记忆系统(文件持久化) |
1163
1244
  | [`09a_structured_data_sql.py`](../examples/standard/09a_structured_data_sql.py) | 示例 9A:关系型数据库 |
1164
1245
  | [`09b_structured_data_graph.py`](../examples/standard/09b_structured_data_graph.py) | 示例 9B:图数据库 |
1246
+ | [`09c_nebula_graph_tool.py`](../examples/standard/09c_nebula_graph_tool.py) | 示例 9C:NebulaGraphTool 最小可执行示例 |
1165
1247
  | [`10_skill_lifecycle.py`](../examples/standard/10_skill_lifecycle.py) | 示例 10:Skill 生命周期 |
1166
1248
  | [`11_orchestration_enhancement.py`](../examples/standard/11_orchestration_enhancement.py) | 示例 11:编排增强 |
1167
1249
  | [`12_run_context_serialization.py`](../examples/standard/12_run_context_serialization.py) | 示例 12:RunContext 序列化与共享状态 |
@@ -1183,9 +1265,12 @@ agent = Agent(name="assistant", instructions="...")
1183
1265
  | [`05_guardrail.py`](../examples/ollama/05_guardrail.py) | 示例 5:安全护栏 |
1184
1266
  | [`06_orchestration.py`](../examples/ollama/06_orchestration.py) | 示例 6:编排 Agent |
1185
1267
  | [`07_sync_async_stream.py`](../examples/ollama/07_sync_async_stream.py) | 示例 7:同步/异步/流式运行 |
1186
- | [`08_memory.py`](../examples/ollama/08_memory.py) | 示例 8:记忆系统 |
1268
+ | [`08a_memory_simple_provider.py`](../examples/ollama/08a_memory_simple_provider.py) | 示例 8A:记忆系统(SimpleMemory) |
1269
+ | [`08b_memory_mem0_provider.py`](../examples/ollama/08b_memory_mem0_provider.py) | 示例 8B:记忆系统(Mem0Provider) |
1270
+ | [`08c_memory_file_provider.py`](../examples/ollama/08c_memory_file_provider.py) | 示例 8C:记忆系统(文件持久化) |
1187
1271
  | [`09a_structured_data_sql.py`](../examples/ollama/09a_structured_data_sql.py) | 示例 9A:关系型数据库 |
1188
1272
  | [`09b_structured_data_graph.py`](../examples/ollama/09b_structured_data_graph.py) | 示例 9B:图数据库 |
1273
+ | [`09c_nebula_graph_tool.py`](../examples/ollama/09c_nebula_graph_tool.py) | 示例 9C:NebulaGraphTool 最小可执行示例 |
1189
1274
  | [`10_skill_lifecycle.py`](../examples/ollama/10_skill_lifecycle.py) | 示例 10:Skill 生命周期 |
1190
1275
  | [`11_orchestration_enhancement.py`](../examples/ollama/11_orchestration_enhancement.py) | 示例 11:编排增强 |
1191
1276
  | [`12_run_context_serialization.py`](../examples/ollama/12_run_context_serialization.py) | 示例 12:RunContext 序列化与共享状态 |
@@ -3,7 +3,7 @@
3
3
  > Python 原生的 Agent 开发框架,内置一等公民级别的 Skill 支持和自研多模型适配层。
4
4
 
5
5
  [![Python](https://img.shields.io/badge/Python-≥3.11-blue.svg)](https://python.org)
6
- [![Version](https://img.shields.io/badge/Version-0.6.2-green.svg)]()
6
+ [![Version](https://img.shields.io/badge/Version-0.7.0-green.svg)]()
7
7
  [![License](https://img.shields.io/badge/License-MIT-yellow.svg)]()
8
8
 
9
9
  ---
@@ -17,6 +17,7 @@
17
17
  | **双协作模式** | Handoff(控制权转移)+ as_tool(Agent 当工具调用),灵活覆盖所有协作场景 |
18
18
  | **编排 Agent** | SequentialAgent / ParallelAgent / LoopAgent,组合出任意复杂的工作流。支持 Loop 动态退出条件与 Parallel 提前取消增强 |
19
19
  | **@function_tool** | 一行装饰器把 Python 函数变成 LLM 工具,自动推断 JSON Schema。内建 `StructuredDataTool` 防止数据库注入 |
20
+ | **图数据统一接口层** | 提供 `GraphAdapter + GraphRepository + GraphQueryTool`,开发/测试可切换 `networkx/litegraph`,生产可切换 `nebula` |
20
21
  | **安全内置** | Input/Output 双向 Guardrail + 三层权限控制;`run_skill_script` 当前为占位执行(SandboxExecutor 预留扩展) |
21
22
  | **记忆系统** | Mem0 集成,跨会话长期记忆 |
22
23
  | **9 个回调点** | before/after × agent/model/tool/handoff + error,任何环节可拦截定制 |
@@ -70,7 +71,7 @@ print(result.final_output)
70
71
 
71
72
  | 文档 | 说明 |
72
73
  |------|------|
73
- | **[QuickStart.md](QuickStart.md)** | 详细入门教程,包含 18 组从简到繁的完整示例(含 9A/9B) |
74
+ | **[QuickStart.md](QuickStart.md)** | 详细入门教程,包含 18 组从简到繁的完整示例(含 8A/8B/8C、9A/9B/9C) |
74
75
  | **[Architecture.md](Architecture.md)** | 架构设计说明:六层分层、设计原则、核心流程 |
75
76
  | **[Reference.md](Reference.md)** | 完整 API 参考手册:所有类、方法、参数说明 |
76
77
 
@@ -21,6 +21,7 @@
21
21
  - [FunctionTool](#functiontool)
22
22
  - [BaseTool / BaseToolset](#basetool--basetoolset)
23
23
  - [StructuredDataTool (结构化数据源)](#structureddatatool-结构化数据源)
24
+ - [Graph 统一接口层(Adapter / Repository / Tool)](#graph-统一接口层adapter--repository--tool)
24
25
  - [Skill 类](#skill-类)
25
26
  - [Skill](#skill)
26
27
  - [SkillFrontmatter](#skillfrontmatter)
@@ -443,6 +444,50 @@ from agentkit.tools.nebula_tool import NebulaGraphTool
443
444
 
444
445
  ---
445
446
 
447
+ ### Graph 统一接口层(Adapter / Repository / Tool)
448
+
449
+ 用于在开发/测试/生产环境之间切换图后端,统一业务侧调用方式。
450
+
451
+ ```python
452
+ from agentkit.tools.graph import (
453
+ GraphRepository,
454
+ GraphQueryTool,
455
+ NodeSpec,
456
+ EdgeSpec,
457
+ QuerySpec,
458
+ create_graph_repository,
459
+ create_graph_repository_from_env,
460
+ )
461
+ ```
462
+
463
+ **核心模型**:
464
+
465
+ | 类型 | 关键字段 | 说明 |
466
+ |------|----------|------|
467
+ | `NodeSpec` | `node_id`、`label`、`properties` | 节点写入规范 |
468
+ | `EdgeSpec` | `source_id`、`target_id`、`edge_type`、`directed`、`properties` | 边写入规范 |
469
+ | `QuerySpec` | `operation`、`node_id/source_id/target_id`、`filters`、`limit` | 图查询参数规范(`neighbors/shortest_path/find_nodes/edges`) |
470
+ | `GraphResult` | `backend`、`rows`、`summary`、`meta` | 统一查询返回结构 |
471
+
472
+ **适配器与仓储**:
473
+
474
+ | 组件 | 说明 |
475
+ |------|------|
476
+ | `GraphAdapter` | 适配器协议,统一 `upsert_node/upsert_edge/query/healthcheck/close` |
477
+ | `NetworkXAdapter` | 开发态图后端,可选本地 JSON 持久化 |
478
+ | `LiteGraphAdapter` | 基于 SQLite 的轻量图后端,适合测试与单机场景 |
479
+ | `NebulaAdapter` | Nebula 生产后端适配器 |
480
+ | `GraphRepository` | 业务统一入口,屏蔽底层后端差异 |
481
+ | `create_graph_repository` | 按 `backend` + `config` 创建仓储 |
482
+ | `create_graph_repository_from_env` | 按环境变量快速创建仓储(`AGENTKIT_GRAPH_*`) |
483
+
484
+ **Tool 集成**:
485
+
486
+ - `GraphQueryTool` 继承 `StructuredDataTool`,参数 Schema 固定为 `GraphQueryArgs`,底层通过 `GraphRepository.query()` 执行并返回标准化 `dict`。
487
+ - 默认支持后端:`networkx` / `litegraph` / `nebula`。
488
+
489
+ ---
490
+
446
491
  ## Skill 类
447
492
 
448
493
  ### Skill
@@ -0,0 +1,92 @@
1
+ # AgentKit 示例测试报告
2
+
3
+ > 测试时间:`2026-04-27`
4
+ > 测试环境:`macOS (Apple Silicon)`
5
+ > 模型:Ollama `qwen3.5:cloud`
6
+ > AgentKit 版本:v0.7.0
7
+ > Thinking 模式:开启(默认)
8
+ > LLM 调用模式:非流式(默认)
9
+ > 缓存:开启(默认)
10
+ > 执行脚本:`examples/test_ollama.py`
11
+
12
+ ---
13
+
14
+ ## 测试结果
15
+
16
+ | # | 示例 | 文件 | 耗时 | 状态 | 说明 |
17
+ |---|------|------|-----:|:----:|------|
18
+ | 1 | 基础对话 | `01_basic_chat.py` | 102.10s | ✅ | 运行通过 |
19
+ | 2 | 工具调用 | `02_tool_calling.py` | 21.27s | ✅ | 运行通过 |
20
+ | 3 | Skill 使用 | `03_skill_usage.py` | 62.60s | ✅ | 运行通过 |
21
+ | 4 | 多 Agent 协作 | `04_multi_agent.py` | 194.60s | ✅ | 运行通过 |
22
+ | 5 | 安全护栏 | `05_guardrail.py` | 8.23s | ✅ | 运行通过 |
23
+ | 5H | HITL 工具触发(Playground 专用) | `05_human_in_the_loop.py` | 0.28s | ✅ | 运行通过 |
24
+ | 6 | 编排 Agent | `06_orchestration.py` | 523.64s | ✅ | 运行通过(本轮最慢) |
25
+ | 7 | 同步/异步/流式 | `07_sync_async_stream.py` | 19.73s | ✅ | 运行通过 |
26
+ | 8 | 记忆系统(综合) | `08_memory.py` | 485.15s | ✅ | 运行通过 |
27
+ | 8A | SimpleMemory | `08a_memory_simple_provider.py` | 30.39s | ✅ | 运行通过 |
28
+ | 8B | Mem0Provider | `08b_memory_mem0_provider.py` | 0.25s | ✅ | 运行通过 |
29
+ | 8C | 文件持久化 Memory | `08c_memory_file_provider.py` | 58.73s | ✅ | 运行通过 |
30
+ | 9A | 结构化数据(SQL) | `09a_structured_data_sql.py` | 7.88s | ✅ | 运行通过 |
31
+ | 9B | 结构化数据(图) | `09b_structured_data_graph.py` | 6.65s | ✅ | 运行通过 |
32
+ | 9C | NebulaGraphTool(直调) | `09c_nebula_graph_tool.py` | 0.32s | ✅ | 运行通过 |
33
+ | 10 | Skill 生命周期 | `10_skill_lifecycle.py` | 2.86s | ✅ | 运行通过 |
34
+ | 11 | 编排增强 | `11_orchestration_enhancement.py` | 70.51s | ✅ | 运行通过 |
35
+ | 12 | 序列化协议 | `12_run_context_serialization.py` | 0.27s | ✅ | 运行通过 |
36
+ | 13 | Human in the Loop | `13_human_in_the_loop.py` | 5.81s | ✅ | 运行通过 |
37
+ | 14 | Event 标准化 | `14_event_standardization.py` | 9.74s | ✅ | 运行通过 |
38
+ | 15 | 多租户隔离 | `15_multi_tenant_isolation.py` | 0.31s | ✅ | 运行通过 |
39
+ | 16 | 生命周期 Hooks | `16_lifecycle_hooks.py` | 0.26s | ✅ | 运行通过 |
40
+ | 17 | Checkpoint + Handoff + Resume | `17_checkpoint_handoff_resume.py` | 0.17s | ✅ | 运行通过 |
41
+ | 18 | ModelCosplay | `18_model_cosplay.py` | 0.17s | ✅ | 运行通过 |
42
+ | 19 | HITL 确定性触发 | `19_hitl_deterministic.py` | 0.17s | ✅ | 运行通过(本轮最快) |
43
+ | | **合计** | | **1612.09s** | **25/25** | |
44
+
45
+ ## 耗时分析
46
+
47
+ - **最快示例**:19 HITL 确定性触发(0.17s)
48
+ - **最慢示例**:6 编排 Agent(523.64s)
49
+ - **耗时集中区间**:涉及多轮推理/记忆写入/编排循环的示例耗时显著更高
50
+
51
+ ## 各示例 LLM 调用次数估算
52
+
53
+ | # | 示例 | LLM 调用次数 | 说明 |
54
+ |---|------|:-----------:|------|
55
+ | 1 | 基础对话 | 1 | 单次对话 |
56
+ | 2 | 工具调用 | ~6 | 多次工具调用与回复生成 |
57
+ | 3 | Skill 使用 | ~9 | load_skill + 工具调用 + 回复 |
58
+ | 4 | 多 Agent 协作 | ~8 | as_tool + handoff 链路 |
59
+ | 5 | 安全护栏 | ~3 | 拦截与放行混合路径 |
60
+ | 5H | HITL 工具触发(Playground 专用) | ~0 | 仅触发挂起事件,不走 LLM |
61
+ | 6 | 编排 Agent | ~12 | Sequential + Parallel + Loop |
62
+ | 7 | 同步/异步/流式 | ~7 | 三种运行模式覆盖 |
63
+ | 8 | 记忆系统(综合) | ~10 | 记忆读写与多轮对话 |
64
+ | 8A | SimpleMemory | ~2 | 轻量关键词检索 |
65
+ | 8B | Mem0Provider | ~0 | 未配置 `OPENAI_API_KEY` 时自动跳过 |
66
+ | 8C | 文件持久化 Memory | ~2 | 本地文件读写 + 记忆检索 |
67
+ | 9A | 结构化数据(SQL) | ~2 | 参数化查询 + 汇总 |
68
+ | 9B | 结构化数据(图) | ~2 | 图查询 + 汇总 |
69
+ | 9C | NebulaGraphTool(直调) | 0 | Mock 连接池直调,不依赖 LLM |
70
+ | 10 | Skill 生命周期 | 1 | 单轮校验 |
71
+ | 11 | 编排增强 | ~4 | loop_condition + early_exit |
72
+ | 12 | RunContext 序列化 | 0 | 纯本地序列化 |
73
+ | 13 | HITL 断点续跑 | ~3 | 挂起 + 恢复 |
74
+ | 14 | 事件协议标准化 | 1 | 标准事件输出 |
75
+ | 15 | 多租户隔离 | ~3 | 多会话隔离验证 |
76
+ | 16 | 生命周期 Hooks | ~2 | Hook 链路验证 |
77
+ | 17 | Checkpoint Handoff 恢复 | 0 | 自定义事件流,不依赖 LLM |
78
+ | 18 | ModelCosplay | 0 | 仅验证模型改写开关与运行时覆盖逻辑,不调用 LLM |
79
+ | 19 | HITL 确定性触发 | 0 | 自定义事件流,不依赖 LLM |
80
+
81
+ ## 已知问题
82
+
83
+ | 问题 | 严重程度 | 说明 |
84
+ |------|:--------:|------|
85
+ | 运行异常 | - | 无,25 个示例全部通过 |
86
+
87
+ ## 运行方式
88
+
89
+ ```bash
90
+ # 在 agentkit 目录执行
91
+ python examples/test_ollama.py
92
+ ```
@@ -21,14 +21,15 @@ agent = Agent(
21
21
  )
22
22
 
23
23
  # 同步运行
24
- result = Runner.run_sync(agent, input="什么是量子计算?请用一句话解释。")
24
+ if __name__ == "__main__":
25
+ result = Runner.run_sync(agent, input="什么是量子计算?请用一句话解释。")
25
26
 
26
- if result.success:
27
- print(f"✅ 回复: {result.final_output}")
28
- else:
29
- print(f"❌ 错误: {result.error}")
27
+ if result.success:
28
+ print(f"✅ 回复: {result.final_output}")
29
+ else:
30
+ print(f"❌ 错误: {result.error}")
30
31
 
31
- # 查看事件流
32
- print("\n📋 事件流:")
33
- for event in result.events:
34
- print(f" [{event.type}] {str(event.data)[:80]}")
32
+ # 查看事件流
33
+ print("\n📋 事件流:")
34
+ for event in result.events:
35
+ print(f" [{event.type}] {str(event.data)[:80]}")
@@ -0,0 +1,42 @@
1
+ """
2
+ 示例 5(Playground/HITL 专用):Human-in-the-loop Agent(Ollama 版)
3
+
4
+ 用途:
5
+ - 提供一个可被 AgentHub `entry` 直接加载的 `agent` 实例;
6
+ - 在工具执行前通过 `request_human_input(...)` 触发挂起,便于在 Playground 中演示 HITL。
7
+ """
8
+ import os
9
+ import sys
10
+
11
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", ".."))
12
+
13
+ from agentkit import Agent
14
+ from agentkit.tools.base_tool import request_human_input
15
+ from agentkit.tools.function_tool import FunctionTool
16
+
17
+
18
+ def confirm_action(action: str) -> str:
19
+ """敏感操作执行前请求人工确认。"""
20
+ request_human_input(f"即将执行敏感操作: {action},请确认 (approve/reject)")
21
+
22
+
23
+ def execute_action(action: str) -> str:
24
+ """执行操作(示例返回)。"""
25
+ return f"操作 '{action}' 已执行。"
26
+
27
+
28
+ confirm_tool = FunctionTool.from_function(confirm_action)
29
+ execute_tool = FunctionTool.from_function(execute_action)
30
+
31
+
32
+ agent = Agent(
33
+ name="hitl-agent",
34
+ instructions=(
35
+ "你是一个需要人工审批的运维助手。"
36
+ "当用户要求执行敏感操作时,必须先调用 confirm_action 请求人工确认;"
37
+ "收到确认后再调用 execute_action。"
38
+ ),
39
+ # 使用纯本地模型,避免 cloud 变体在未鉴权/网络抖动时触发远端 502。
40
+ model="ollama/qwen3.5:4b",
41
+ tools=[confirm_tool, execute_tool],
42
+ )
@@ -0,0 +1,59 @@
1
+ import asyncio
2
+ import os
3
+ import sys
4
+
5
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", ".."))
6
+
7
+ from agentkit import Agent, BaseMemoryProvider, Memory, Runner
8
+
9
+ MODEL = "ollama/qwen3.5:cloud"
10
+
11
+
12
+ class SimpleMemory(BaseMemoryProvider):
13
+ def __init__(self) -> None:
14
+ self._store: list[Memory] = []
15
+ self._counter = 0
16
+
17
+ async def add(self, content, *, user_id=None, agent_id=None, metadata=None):
18
+ self._counter += 1
19
+ item = Memory(id=str(self._counter), content=content)
20
+ self._store.append(item)
21
+ return [item]
22
+
23
+ async def search(self, query, *, user_id=None, agent_id=None, limit=10):
24
+ query_chars = set(query)
25
+ scored: list[tuple[int, Memory]] = []
26
+ for item in self._store:
27
+ overlap = len(query_chars & set(item.content))
28
+ if overlap > 0:
29
+ scored.append((overlap, item))
30
+ scored.sort(reverse=True, key=lambda x: x[0])
31
+ return [m for _, m in scored[:limit]]
32
+
33
+ async def get_all(self, *, user_id=None, agent_id=None):
34
+ return list(self._store)
35
+
36
+ async def delete(self, memory_id):
37
+ self._store = [m for m in self._store if m.id != memory_id]
38
+ return True
39
+
40
+
41
+ async def main() -> None:
42
+ print("=== 示例 8A:SimpleMemory ===")
43
+ memory = SimpleMemory()
44
+ agent = Agent(
45
+ name="remembering",
46
+ instructions="你是贴心助手。根据记忆回答,回答简洁。",
47
+ model=MODEL,
48
+ memory=memory,
49
+ memory_async_write=False,
50
+ )
51
+
52
+ await Runner.run(agent, input="我叫小明,喜欢咖啡,讨厌茶。", user_id="user_001")
53
+ result = await Runner.run(agent, input="帮我推荐一杯饮料。", user_id="user_001")
54
+ print("推荐:", result.final_output)
55
+ print("记忆条数:", len(await memory.get_all()))
56
+
57
+
58
+ if __name__ == "__main__":
59
+ asyncio.run(main())
@@ -0,0 +1,57 @@
1
+ import asyncio
2
+ import os
3
+ import sys
4
+
5
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", ".."))
6
+
7
+ from agentkit import Agent, Runner
8
+
9
+ MODEL = "ollama/qwen3.5:cloud"
10
+
11
+
12
+ async def main() -> None:
13
+ print("=== 示例 8B:Mem0Provider ===")
14
+ try:
15
+ from agentkit.memory.mem0_provider import Mem0Provider
16
+ except Exception:
17
+ print("未安装 mem0ai,跳过运行。")
18
+ print("安装: pip install mem0ai")
19
+ print("并启动 qdrant: docker run -p 6333:6333 qdrant/qdrant")
20
+ return
21
+
22
+ if not os.getenv("OPENAI_API_KEY"):
23
+ print("未设置 OPENAI_API_KEY,跳过运行。")
24
+ return
25
+
26
+ try:
27
+ memory = Mem0Provider(
28
+ {
29
+ "vector_store": {
30
+ "provider": "qdrant",
31
+ "config": {
32
+ "collection_name": "agentkit_quickstart",
33
+ "host": "localhost",
34
+ "port": 6333,
35
+ },
36
+ }
37
+ }
38
+ )
39
+ except Exception as exc:
40
+ print(f"Mem0 初始化失败,跳过运行: {exc}")
41
+ return
42
+
43
+ agent = Agent(
44
+ name="mem0-assistant",
45
+ instructions="你是贴心助手。根据记忆回答,回答简洁。",
46
+ model=MODEL,
47
+ memory=memory,
48
+ memory_async_write=False,
49
+ )
50
+
51
+ await Runner.run(agent, input="记住:我喜欢低糖拿铁。", user_id="user_001")
52
+ result = await Runner.run(agent, input="给我推荐一杯饮料。", user_id="user_001")
53
+ print("推荐:", result.final_output)
54
+
55
+
56
+ if __name__ == "__main__":
57
+ asyncio.run(main())