connectonion 0.6.2__py3-none-any.whl → 0.6.4__py3-none-any.whl

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 (410) hide show
  1. connectonion/__init__.py +46 -9
  2. connectonion/cli/__init__.py +11 -1
  3. connectonion/cli/browser_agent/__init__.py +11 -1
  4. connectonion/cli/browser_agent/browser.py +13 -3
  5. connectonion/cli/browser_agent/element_finder.py +8 -0
  6. connectonion/cli/browser_agent/highlight_screenshot.py +9 -1
  7. connectonion/cli/browser_agent/scroll.py +8 -0
  8. connectonion/cli/co_ai/__init__.py +6 -0
  9. connectonion/cli/co_ai/agent.py +87 -0
  10. connectonion/cli/co_ai/agents/__init__.py +5 -0
  11. connectonion/cli/co_ai/agents/registry.py +57 -0
  12. connectonion/cli/co_ai/commands/__init__.py +45 -0
  13. connectonion/cli/co_ai/commands/compact.py +173 -0
  14. connectonion/cli/co_ai/commands/cost.py +77 -0
  15. connectonion/cli/co_ai/commands/export.py +60 -0
  16. connectonion/cli/co_ai/commands/help.py +80 -0
  17. connectonion/cli/co_ai/commands/init.py +101 -0
  18. connectonion/cli/co_ai/commands/sessions.py +55 -0
  19. connectonion/cli/co_ai/commands/tasks.py +63 -0
  20. connectonion/cli/co_ai/commands/undo.py +103 -0
  21. connectonion/cli/co_ai/context.py +127 -0
  22. connectonion/cli/co_ai/main.py +52 -0
  23. connectonion/cli/co_ai/plugins/__init__.py +5 -0
  24. connectonion/cli/co_ai/plugins/system_reminder.py +154 -0
  25. connectonion/cli/co_ai/prompts/agents/explore.md +79 -0
  26. connectonion/cli/co_ai/prompts/agents/plan.md +60 -0
  27. connectonion/cli/co_ai/prompts/assembler.py +303 -0
  28. connectonion/cli/{docs/co-vibecoding-principles-docs-contexts-all-in-one.md → co_ai/prompts/connectonion/README.md} +26 -0
  29. connectonion/cli/co_ai/prompts/connectonion/api.md +457 -0
  30. connectonion/cli/co_ai/prompts/connectonion/cli/README.md +805 -0
  31. connectonion/cli/co_ai/prompts/connectonion/cli/auth.md +46 -0
  32. connectonion/cli/co_ai/prompts/connectonion/cli/browser.md +235 -0
  33. connectonion/cli/co_ai/prompts/connectonion/cli/copy.md +184 -0
  34. connectonion/cli/co_ai/prompts/connectonion/cli/create.md +335 -0
  35. connectonion/cli/co_ai/prompts/connectonion/cli/init.md +431 -0
  36. connectonion/cli/co_ai/prompts/connectonion/co-directory-structure.md +214 -0
  37. connectonion/cli/co_ai/prompts/connectonion/concepts/agent.md +1078 -0
  38. connectonion/cli/co_ai/prompts/connectonion/concepts/events.md +816 -0
  39. connectonion/cli/co_ai/prompts/connectonion/concepts/llm_do.md +256 -0
  40. connectonion/cli/co_ai/prompts/connectonion/concepts/max_iterations.md +362 -0
  41. connectonion/cli/co_ai/prompts/connectonion/concepts/models.md +641 -0
  42. connectonion/cli/co_ai/prompts/connectonion/concepts/plugins.md +100 -0
  43. connectonion/cli/co_ai/prompts/connectonion/concepts/prompts.md +122 -0
  44. connectonion/cli/co_ai/prompts/connectonion/concepts/tools.md +512 -0
  45. connectonion/cli/co_ai/prompts/connectonion/concepts/transcribe.md +156 -0
  46. connectonion/cli/co_ai/prompts/connectonion/concepts/trust.md +291 -0
  47. connectonion/cli/co_ai/prompts/connectonion/debug/README.md +18 -0
  48. connectonion/cli/co_ai/prompts/connectonion/debug/auto_debug.md +1026 -0
  49. connectonion/cli/co_ai/prompts/connectonion/debug/console.md +129 -0
  50. connectonion/cli/co_ai/prompts/connectonion/debug/eval-format.md +178 -0
  51. connectonion/cli/co_ai/prompts/connectonion/debug/eval.md +230 -0
  52. connectonion/cli/co_ai/prompts/connectonion/debug/exceptions.md +307 -0
  53. connectonion/cli/co_ai/prompts/connectonion/debug/log.md +117 -0
  54. connectonion/cli/co_ai/prompts/connectonion/debug/xray.md +215 -0
  55. connectonion/cli/co_ai/prompts/connectonion/design-decisions/001-choosing-input-method.md +202 -0
  56. connectonion/cli/co_ai/prompts/connectonion/design-decisions/002-choosing-llm-function-name.md +202 -0
  57. connectonion/cli/co_ai/prompts/connectonion/design-decisions/003-choosing-trust-keyword.md +141 -0
  58. connectonion/cli/co_ai/prompts/connectonion/design-decisions/004-cli-create-flow.md +117 -0
  59. connectonion/cli/co_ai/prompts/connectonion/design-decisions/005-designing-agent-network-protocol.md +503 -0
  60. connectonion/cli/co_ai/prompts/connectonion/design-decisions/006-agent-address-format.md +305 -0
  61. connectonion/cli/co_ai/prompts/connectonion/design-decisions/007-authentication-backend-design.md +240 -0
  62. connectonion/cli/co_ai/prompts/connectonion/design-decisions/008-naming-is-hard.md +228 -0
  63. connectonion/cli/co_ai/prompts/connectonion/design-decisions/009-why-connect-function.md +167 -0
  64. connectonion/cli/co_ai/prompts/connectonion/design-decisions/010-cli-ux-progressive-disclosure.md +176 -0
  65. connectonion/cli/co_ai/prompts/connectonion/design-decisions/011-global-config-identity-management.md +357 -0
  66. connectonion/cli/co_ai/prompts/connectonion/design-decisions/012-tool-execution-separation.md +259 -0
  67. connectonion/cli/co_ai/prompts/connectonion/design-decisions/013-debug-and-logging-design.md +253 -0
  68. connectonion/cli/co_ai/prompts/connectonion/design-decisions/014-hook-system-design.md +510 -0
  69. connectonion/cli/co_ai/prompts/connectonion/design-decisions/015-interactive-auto-debug-design.md +837 -0
  70. connectonion/cli/co_ai/prompts/connectonion/design-decisions/016-why-no-zero-knowledge-proofs.md +358 -0
  71. connectonion/cli/co_ai/prompts/connectonion/design-decisions/017-session-logging-and-eval-format.md +120 -0
  72. connectonion/cli/co_ai/prompts/connectonion/design-decisions/018-event-api-naming.md +274 -0
  73. connectonion/cli/co_ai/prompts/connectonion/design-decisions/019-agent-lifecycle-design.md +655 -0
  74. connectonion/cli/co_ai/prompts/connectonion/design-decisions/020-trust-system-and-network-architecture.md +503 -0
  75. connectonion/cli/co_ai/prompts/connectonion/design-decisions/021-task-storage-jsonl-design.md +496 -0
  76. connectonion/cli/co_ai/prompts/connectonion/design-decisions/022-raw-asgi-implementation.md +273 -0
  77. connectonion/cli/co_ai/prompts/connectonion/examples/agent_reasoning.md +62 -0
  78. connectonion/cli/co_ai/prompts/connectonion/examples/atomic_tools.md +24 -0
  79. connectonion/cli/co_ai/prompts/connectonion/examples/load_guide.md +18 -0
  80. connectonion/cli/co_ai/prompts/connectonion/examples.md +0 -0
  81. connectonion/cli/co_ai/prompts/connectonion/hook-system-options.md +364 -0
  82. connectonion/cli/co_ai/prompts/connectonion/index.md +162 -0
  83. connectonion/cli/co_ai/prompts/connectonion/integrations/README.md +12 -0
  84. connectonion/cli/co_ai/prompts/connectonion/integrations/auth.md +450 -0
  85. connectonion/cli/co_ai/prompts/connectonion/integrations/google.md +431 -0
  86. connectonion/cli/co_ai/prompts/connectonion/integrations/microsoft.md +370 -0
  87. connectonion/cli/co_ai/prompts/connectonion/network/README.md +14 -0
  88. connectonion/cli/co_ai/prompts/connectonion/network/connect.md +543 -0
  89. connectonion/cli/co_ai/prompts/connectonion/network/connection.md +538 -0
  90. connectonion/cli/co_ai/prompts/connectonion/network/deploy.md +123 -0
  91. connectonion/cli/co_ai/prompts/connectonion/network/host.md +1049 -0
  92. connectonion/cli/co_ai/prompts/connectonion/network/protocol/agent-relay-protocol.md +495 -0
  93. connectonion/cli/co_ai/prompts/connectonion/network/protocol/announce-message.md +115 -0
  94. connectonion/cli/co_ai/prompts/connectonion/principles.md +124 -0
  95. connectonion/cli/co_ai/prompts/connectonion/quickstart.md +261 -0
  96. connectonion/cli/co_ai/prompts/connectonion/roadmap.md +81 -0
  97. connectonion/cli/co_ai/prompts/connectonion/templates/README.md +77 -0
  98. connectonion/cli/co_ai/prompts/connectonion/templates/meta-agent.md +152 -0
  99. connectonion/cli/co_ai/prompts/connectonion/templates/minimal.md +105 -0
  100. connectonion/cli/co_ai/prompts/connectonion/templates/playwright.md +130 -0
  101. connectonion/cli/co_ai/prompts/connectonion/templates/web-research.md +144 -0
  102. connectonion/cli/co_ai/prompts/connectonion/tui/README.md +95 -0
  103. connectonion/cli/co_ai/prompts/connectonion/tui/chat.md +181 -0
  104. connectonion/cli/co_ai/prompts/connectonion/tui/divider.md +63 -0
  105. connectonion/cli/co_ai/prompts/connectonion/tui/dropdown.md +83 -0
  106. connectonion/cli/co_ai/prompts/connectonion/tui/footer.md +44 -0
  107. connectonion/cli/co_ai/prompts/connectonion/tui/fuzzy.md +68 -0
  108. connectonion/cli/co_ai/prompts/connectonion/tui/input.md +84 -0
  109. connectonion/cli/co_ai/prompts/connectonion/tui/keys.md +77 -0
  110. connectonion/cli/co_ai/prompts/connectonion/tui/pick.md +71 -0
  111. connectonion/cli/co_ai/prompts/connectonion/tui/providers.md +89 -0
  112. connectonion/cli/co_ai/prompts/connectonion/tui/status_bar.md +67 -0
  113. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/README.md +156 -0
  114. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/calendar_plugin.md +68 -0
  115. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/eval.md +89 -0
  116. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/gmail_plugin.md +68 -0
  117. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/image_result_formatter.md +74 -0
  118. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/re_act.md +86 -0
  119. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/shell_approval.md +69 -0
  120. connectonion/cli/co_ai/prompts/connectonion/useful_tools/README.md +81 -0
  121. connectonion/cli/co_ai/prompts/connectonion/useful_tools/diff_writer.md +138 -0
  122. connectonion/cli/co_ai/prompts/connectonion/useful_tools/get_emails.md +499 -0
  123. connectonion/cli/co_ai/prompts/connectonion/useful_tools/gmail.md +135 -0
  124. connectonion/cli/co_ai/prompts/connectonion/useful_tools/google_calendar.md +106 -0
  125. connectonion/cli/co_ai/prompts/connectonion/useful_tools/memory.md +486 -0
  126. connectonion/cli/co_ai/prompts/connectonion/useful_tools/microsoft_calendar.md +106 -0
  127. connectonion/cli/co_ai/prompts/connectonion/useful_tools/outlook.md +120 -0
  128. connectonion/cli/co_ai/prompts/connectonion/useful_tools/send_email.md +403 -0
  129. connectonion/cli/co_ai/prompts/connectonion/useful_tools/shell.md +95 -0
  130. connectonion/cli/co_ai/prompts/connectonion/useful_tools/slash_command.md +96 -0
  131. connectonion/cli/co_ai/prompts/connectonion/useful_tools/terminal.md +97 -0
  132. connectonion/cli/co_ai/prompts/connectonion/useful_tools/todo_list.md +252 -0
  133. connectonion/cli/co_ai/prompts/connectonion/useful_tools/web_fetch.md +130 -0
  134. connectonion/cli/co_ai/prompts/connectonion/vibe-coding-guide.md +97 -0
  135. connectonion/cli/co_ai/prompts/connectonion/windows-support.md +258 -0
  136. connectonion/cli/co_ai/prompts/main.md +247 -0
  137. connectonion/cli/co_ai/prompts/summarization.md +55 -0
  138. connectonion/cli/co_ai/prompts/system-reminders/agent.md +23 -0
  139. connectonion/cli/co_ai/prompts/system-reminders/plan_mode.md +13 -0
  140. connectonion/cli/co_ai/prompts/system-reminders/security.md +14 -0
  141. connectonion/cli/co_ai/prompts/system-reminders/simplicity.md +14 -0
  142. connectonion/cli/co_ai/prompts/tools/ask_user.md +61 -0
  143. connectonion/cli/co_ai/prompts/tools/background.md +57 -0
  144. connectonion/cli/co_ai/prompts/tools/edit.md +90 -0
  145. connectonion/cli/co_ai/prompts/tools/glob.md +52 -0
  146. connectonion/cli/co_ai/prompts/tools/grep.md +55 -0
  147. connectonion/cli/co_ai/prompts/tools/plan_mode.md +80 -0
  148. connectonion/cli/co_ai/prompts/tools/read.md +40 -0
  149. connectonion/cli/co_ai/prompts/tools/shell.md +67 -0
  150. connectonion/cli/co_ai/prompts/tools/task.md +51 -0
  151. connectonion/cli/co_ai/prompts/tools/todo.md +139 -0
  152. connectonion/cli/co_ai/prompts/tools/write.md +47 -0
  153. connectonion/cli/co_ai/prompts/workflow.md +89 -0
  154. connectonion/cli/co_ai/sessions.py +110 -0
  155. connectonion/cli/co_ai/skills/__init__.py +37 -0
  156. connectonion/cli/co_ai/skills/builtin/commit/SKILL.md +63 -0
  157. connectonion/cli/co_ai/skills/builtin/review-pr/SKILL.md +76 -0
  158. connectonion/cli/co_ai/skills/loader.py +166 -0
  159. connectonion/cli/co_ai/skills/tool.py +46 -0
  160. connectonion/cli/co_ai/tools/__init__.py +92 -0
  161. connectonion/cli/co_ai/tools/ask_user.py +35 -0
  162. connectonion/cli/co_ai/tools/background.py +201 -0
  163. connectonion/cli/co_ai/tools/diff_writer.py +291 -0
  164. connectonion/cli/co_ai/tools/edit.py +89 -0
  165. connectonion/cli/co_ai/tools/glob.py +84 -0
  166. connectonion/cli/co_ai/tools/grep.py +158 -0
  167. connectonion/cli/co_ai/tools/load_guide.py +23 -0
  168. connectonion/cli/co_ai/tools/multi_edit.py +116 -0
  169. connectonion/cli/co_ai/tools/plan_mode.py +169 -0
  170. connectonion/cli/co_ai/tools/read.py +61 -0
  171. connectonion/cli/co_ai/tools/task.py +59 -0
  172. connectonion/cli/co_ai/tools/todo_list.py +159 -0
  173. connectonion/cli/co_ai/tools/write.py +126 -0
  174. connectonion/cli/commands/__init__.py +11 -1
  175. connectonion/cli/commands/ai_commands.py +34 -0
  176. connectonion/cli/commands/copy_commands.py +55 -6
  177. connectonion/cli/commands/create.py +20 -17
  178. connectonion/cli/commands/init.py +19 -22
  179. connectonion/cli/commands/project_cmd_lib.py +15 -0
  180. connectonion/cli/main.py +11 -0
  181. connectonion/console.py +15 -1
  182. connectonion/core/__init__.py +10 -1
  183. connectonion/core/agent.py +37 -16
  184. connectonion/core/exceptions.py +74 -0
  185. connectonion/core/llm.py +54 -6
  186. connectonion/core/tool_executor.py +32 -31
  187. connectonion/core/tool_factory.py +47 -10
  188. connectonion/debug/__init__.py +10 -1
  189. connectonion/debug/debug_explainer/__init__.py +10 -1
  190. connectonion/debug/execution_analyzer/__init__.py +10 -1
  191. connectonion/debug/execution_analyzer/execution_analysis.py +5 -2
  192. connectonion/debug/runtime_inspector/__init__.py +10 -1
  193. connectonion/docs/.package-ignore +6 -0
  194. connectonion/docs/README.md +2036 -0
  195. connectonion/docs/api.md +457 -0
  196. connectonion/docs/archive/001-ai-agent-is-just-prompt-plus-function.md +249 -0
  197. connectonion/docs/archive/README.md +53 -0
  198. connectonion/docs/archive/archive/consolidation-plan.md +72 -0
  199. connectonion/docs/archive/archive/core-principles-extracted.md +239 -0
  200. connectonion/docs/archive/archive/master-principles.md +222 -0
  201. connectonion/docs/archive/archive/principles.md +293 -0
  202. connectonion/docs/archive/archive/simplicity-principles.md +221 -0
  203. connectonion/docs/archive/attack-defense-insights.md +410 -0
  204. connectonion/docs/archive/business-model.md +305 -0
  205. connectonion/docs/archive/core-principles-unified.md +190 -0
  206. connectonion/docs/archive/discussion-journey.md +178 -0
  207. connectonion/docs/archive/economic-analysis.md +323 -0
  208. connectonion/docs/archive/features/01-share-and-find.md +256 -0
  209. connectonion/docs/archive/features/02-agent-authentication.md +93 -0
  210. connectonion/docs/archive/features/03-test-before-trust.md +71 -0
  211. connectonion/docs/archive/features/06-reliability-and-offline.md +197 -0
  212. connectonion/docs/archive/features/README.md +46 -0
  213. connectonion/docs/archive/features-roadmap.md +247 -0
  214. connectonion/docs/archive/mcp-comparison-insights.md +215 -0
  215. connectonion/docs/archive/migration-strategy.md +571 -0
  216. connectonion/docs/archive/mini-whitepaper.md +293 -0
  217. connectonion/docs/archive/network-protocol.md +394 -0
  218. connectonion/docs/archive/semantic-revolution.md +367 -0
  219. connectonion/docs/archive/technical-architecture.md +453 -0
  220. connectonion/docs/archive/the-semantic-insight.md +207 -0
  221. connectonion/docs/archive/threat-model.md +164 -0
  222. connectonion/docs/cli/README.md +805 -0
  223. connectonion/docs/cli/auth.md +46 -0
  224. connectonion/docs/cli/browser.md +235 -0
  225. connectonion/docs/cli/copy.md +232 -0
  226. connectonion/docs/cli/create.md +335 -0
  227. connectonion/docs/cli/init.md +431 -0
  228. connectonion/docs/co-directory-structure.md +214 -0
  229. connectonion/docs/concepts/agent.md +1078 -0
  230. connectonion/docs/concepts/events.md +699 -0
  231. connectonion/docs/concepts/llm_do.md +256 -0
  232. connectonion/docs/concepts/max_iterations.md +362 -0
  233. connectonion/docs/concepts/models.md +641 -0
  234. connectonion/docs/concepts/plugins.md +101 -0
  235. connectonion/docs/concepts/prompts.md +122 -0
  236. connectonion/docs/concepts/session.md +428 -0
  237. connectonion/docs/concepts/tools.md +512 -0
  238. connectonion/docs/concepts/transcribe.md +156 -0
  239. connectonion/docs/concepts/trust.md +291 -0
  240. connectonion/docs/connectonion.md +1256 -0
  241. connectonion/docs/debug/README.md +18 -0
  242. connectonion/docs/debug/auto_debug.md +1026 -0
  243. connectonion/docs/debug/console.md +129 -0
  244. connectonion/docs/debug/eval-format.md +178 -0
  245. connectonion/docs/debug/eval.md +230 -0
  246. connectonion/docs/debug/exceptions.md +307 -0
  247. connectonion/docs/debug/log.md +117 -0
  248. connectonion/docs/debug/xray.md +215 -0
  249. connectonion/docs/design-decisions/001-choosing-input-method.md +202 -0
  250. connectonion/docs/design-decisions/002-choosing-llm-function-name.md +202 -0
  251. connectonion/docs/design-decisions/003-choosing-trust-keyword.md +141 -0
  252. connectonion/docs/design-decisions/004-cli-create-flow.md +117 -0
  253. connectonion/docs/design-decisions/005-designing-agent-network-protocol.md +503 -0
  254. connectonion/docs/design-decisions/006-agent-address-format.md +305 -0
  255. connectonion/docs/design-decisions/007-authentication-backend-design.md +240 -0
  256. connectonion/docs/design-decisions/008-naming-is-hard.md +228 -0
  257. connectonion/docs/design-decisions/009-why-connect-function.md +167 -0
  258. connectonion/docs/design-decisions/010-cli-ux-progressive-disclosure.md +176 -0
  259. connectonion/docs/design-decisions/011-global-config-identity-management.md +357 -0
  260. connectonion/docs/design-decisions/012-tool-execution-separation.md +259 -0
  261. connectonion/docs/design-decisions/013-debug-and-logging-design.md +253 -0
  262. connectonion/docs/design-decisions/014-hook-system-design.md +510 -0
  263. connectonion/docs/design-decisions/015-interactive-auto-debug-design.md +837 -0
  264. connectonion/docs/design-decisions/016-why-no-zero-knowledge-proofs.md +358 -0
  265. connectonion/docs/design-decisions/017-session-logging-and-eval-format.md +120 -0
  266. connectonion/docs/design-decisions/018-event-api-naming.md +274 -0
  267. connectonion/docs/design-decisions/019-agent-lifecycle-design.md +655 -0
  268. connectonion/docs/design-decisions/020-trust-system-and-network-architecture.md +503 -0
  269. connectonion/docs/design-decisions/021-task-storage-jsonl-design.md +496 -0
  270. connectonion/docs/design-decisions/022-raw-asgi-implementation.md +273 -0
  271. connectonion/docs/examples.md +0 -0
  272. connectonion/docs/hook-system-options.md +364 -0
  273. connectonion/docs/integrations/README.md +12 -0
  274. connectonion/docs/integrations/auth.md +450 -0
  275. connectonion/docs/integrations/google.md +431 -0
  276. connectonion/docs/integrations/microsoft.md +370 -0
  277. connectonion/docs/network/README.md +14 -0
  278. connectonion/docs/network/connect.md +629 -0
  279. connectonion/docs/network/deploy.md +124 -0
  280. connectonion/docs/network/host.md +1087 -0
  281. connectonion/docs/network/io.md +538 -0
  282. connectonion/docs/network/protocol/agent-relay-protocol.md +495 -0
  283. connectonion/docs/network/protocol/announce-message.md +115 -0
  284. connectonion/docs/principles.md +124 -0
  285. connectonion/docs/quickstart.md +261 -0
  286. connectonion/docs/roadmap.md +81 -0
  287. connectonion/docs/templates/README.md +77 -0
  288. connectonion/docs/templates/meta-agent.md +152 -0
  289. connectonion/docs/templates/minimal.md +105 -0
  290. connectonion/docs/templates/playwright.md +130 -0
  291. connectonion/docs/templates/web-research.md +144 -0
  292. connectonion/docs/tui/README.md +95 -0
  293. connectonion/docs/tui/chat.md +181 -0
  294. connectonion/docs/tui/divider.md +63 -0
  295. connectonion/docs/tui/dropdown.md +83 -0
  296. connectonion/docs/tui/footer.md +44 -0
  297. connectonion/docs/tui/fuzzy.md +68 -0
  298. connectonion/docs/tui/input.md +84 -0
  299. connectonion/docs/tui/keys.md +77 -0
  300. connectonion/docs/tui/pick.md +71 -0
  301. connectonion/docs/tui/providers.md +89 -0
  302. connectonion/docs/tui/status_bar.md +67 -0
  303. connectonion/docs/useful_plugins/README.md +160 -0
  304. connectonion/docs/useful_plugins/calendar_plugin.md +68 -0
  305. connectonion/docs/useful_plugins/eval.md +89 -0
  306. connectonion/docs/useful_plugins/gmail_plugin.md +68 -0
  307. connectonion/docs/useful_plugins/image_result_formatter.md +74 -0
  308. connectonion/docs/useful_plugins/re_act.md +86 -0
  309. connectonion/docs/useful_plugins/shell_approval.md +69 -0
  310. connectonion/docs/useful_plugins/system_reminder.md +210 -0
  311. connectonion/docs/useful_plugins/tool_approval.md +139 -0
  312. connectonion/docs/useful_prompts/README.md +127 -0
  313. connectonion/docs/useful_prompts/coding_agent.md +214 -0
  314. connectonion/docs/useful_tools/README.md +81 -0
  315. connectonion/docs/useful_tools/ask_user.md +103 -0
  316. connectonion/docs/useful_tools/diff_writer.md +158 -0
  317. connectonion/docs/useful_tools/get_emails.md +519 -0
  318. connectonion/docs/useful_tools/gmail.md +155 -0
  319. connectonion/docs/useful_tools/google_calendar.md +126 -0
  320. connectonion/docs/useful_tools/memory.md +506 -0
  321. connectonion/docs/useful_tools/microsoft_calendar.md +126 -0
  322. connectonion/docs/useful_tools/outlook.md +140 -0
  323. connectonion/docs/useful_tools/send_email.md +423 -0
  324. connectonion/docs/useful_tools/shell.md +115 -0
  325. connectonion/docs/useful_tools/slash_command.md +116 -0
  326. connectonion/docs/useful_tools/terminal.md +115 -0
  327. connectonion/docs/useful_tools/todo_list.md +272 -0
  328. connectonion/docs/useful_tools/web_fetch.md +150 -0
  329. connectonion/docs/vibe-coding-guide.md +97 -0
  330. connectonion/docs/windows-support.md +258 -0
  331. connectonion/logger.py +3 -3
  332. connectonion/network/__init__.py +19 -6
  333. connectonion/network/asgi/__init__.py +81 -0
  334. connectonion/network/asgi/http.py +205 -0
  335. connectonion/network/asgi/websocket.py +217 -0
  336. connectonion/network/connect.py +232 -185
  337. connectonion/network/host/__init__.py +59 -0
  338. connectonion/network/host/auth.py +191 -0
  339. connectonion/network/host/routes.py +135 -0
  340. connectonion/network/host/server.py +289 -0
  341. connectonion/network/host/session.py +78 -0
  342. connectonion/network/io/__init__.py +21 -0
  343. connectonion/network/{connection.py → io/base.py} +17 -42
  344. connectonion/network/io/websocket.py +55 -0
  345. connectonion/network/relay.py +37 -16
  346. connectonion/network/trust/__init__.py +30 -0
  347. connectonion/network/trust/factory.py +138 -0
  348. connectonion/network/{trust_agents.py → trust/prompts.py} +3 -3
  349. connectonion/network/{trust_functions.py → trust/tools.py} +2 -2
  350. connectonion/prompt_files/__init__.py +11 -1
  351. connectonion/prompt_files/react_acknowledge.md +26 -0
  352. connectonion/prompts.py +10 -1
  353. connectonion/tui/chat.py +10 -1
  354. connectonion/tui/divider.py +10 -1
  355. connectonion/tui/dropdown.py +10 -1
  356. connectonion/tui/footer.py +8 -0
  357. connectonion/tui/fuzzy.py +11 -1
  358. connectonion/tui/input.py +118 -70
  359. connectonion/tui/keys.py +133 -6
  360. connectonion/tui/providers.py +11 -1
  361. connectonion/tui/status_bar.py +10 -1
  362. connectonion/useful_events_handlers/__init__.py +8 -0
  363. connectonion/useful_events_handlers/reflect.py +19 -4
  364. connectonion/useful_plugins/__init__.py +3 -1
  365. connectonion/useful_plugins/eval.py +2 -2
  366. connectonion/useful_plugins/gmail_plugin.py +3 -3
  367. connectonion/useful_plugins/image_result_formatter.py +3 -3
  368. connectonion/useful_plugins/re_act.py +114 -28
  369. connectonion/useful_plugins/shell_approval.py +2 -2
  370. connectonion/useful_plugins/system_reminder.py +103 -0
  371. connectonion/useful_plugins/tool_approval.py +233 -0
  372. connectonion/useful_plugins/ui_stream.py +18 -133
  373. connectonion/useful_prompts/README.md +61 -0
  374. connectonion/useful_prompts/__init__.py +45 -0
  375. connectonion/useful_prompts/coding_agent/README.md +106 -0
  376. connectonion/useful_prompts/coding_agent/assembler.py +123 -0
  377. connectonion/useful_prompts/coding_agent/prompts/main.md +227 -0
  378. connectonion/useful_prompts/coding_agent/prompts/tools/ask_user.md +61 -0
  379. connectonion/useful_prompts/coding_agent/prompts/tools/background.md +57 -0
  380. connectonion/useful_prompts/coding_agent/prompts/tools/edit.md +90 -0
  381. connectonion/useful_prompts/coding_agent/prompts/tools/glob.md +52 -0
  382. connectonion/useful_prompts/coding_agent/prompts/tools/grep.md +55 -0
  383. connectonion/useful_prompts/coding_agent/prompts/tools/plan_mode.md +80 -0
  384. connectonion/useful_prompts/coding_agent/prompts/tools/read.md +40 -0
  385. connectonion/useful_prompts/coding_agent/prompts/tools/shell.md +67 -0
  386. connectonion/useful_prompts/coding_agent/prompts/tools/task.md +51 -0
  387. connectonion/useful_prompts/coding_agent/prompts/tools/todo.md +139 -0
  388. connectonion/useful_prompts/coding_agent/prompts/tools/write.md +48 -0
  389. connectonion/useful_prompts/system-reminders/security-warning.md +14 -0
  390. connectonion/useful_prompts/system-reminders/test-reminder.md +11 -0
  391. connectonion/useful_tools/__init__.py +31 -4
  392. connectonion/useful_tools/ask_user.py +35 -0
  393. connectonion/useful_tools/bash.py +69 -0
  394. connectonion/useful_tools/diff_writer.py +186 -94
  395. connectonion/useful_tools/edit.py +102 -0
  396. connectonion/useful_tools/glob_files.py +97 -0
  397. connectonion/useful_tools/grep_files.py +171 -0
  398. connectonion/useful_tools/multi_edit.py +116 -0
  399. connectonion/useful_tools/read_file.py +73 -0
  400. connectonion/useful_tools/shell.py +50 -45
  401. connectonion/useful_tools/write_file.py +129 -0
  402. {connectonion-0.6.2.dist-info → connectonion-0.6.4.dist-info}/METADATA +10 -3
  403. connectonion-0.6.4.dist-info/RECORD +472 -0
  404. connectonion/network/asgi.py +0 -407
  405. connectonion/network/host.py +0 -616
  406. connectonion/network/trust.py +0 -166
  407. connectonion-0.6.2.dist-info/RECORD +0 -129
  408. /connectonion/cli/{docs → co_ai/prompts/connectonion}/connectonion.md +0 -0
  409. {connectonion-0.6.2.dist-info → connectonion-0.6.4.dist-info}/WHEEL +0 -0
  410. {connectonion-0.6.2.dist-info → connectonion-0.6.4.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,2036 @@
1
+ # ConnectOnion Framework - Complete Reference for AI Assistants
2
+
3
+ ## Documentation Directory Structure
4
+
5
+ ```
6
+ .co/docs/
7
+ ├── README.md # This file - complete reference for vibe coding
8
+ ├── quickstart.md # 60-second getting started guide
9
+ ├── api.md # Full API reference
10
+ ├── connectonion.md # Framework architecture deep dive
11
+ ├── examples.md # Code examples and patterns
12
+ ├── principles.md # Design philosophy
13
+ ├── cli/ # CLI commands documentation
14
+ ├── concepts/ # Core concepts (agents, tools, trust)
15
+ ├── debug/ # Debugging and @xray documentation
16
+ ├── design-decisions/ # Why things are built this way
17
+ ├── integrations/ # Third-party integrations
18
+ ├── network/ # Agent networking and communication
19
+ ├── templates/ # Project templates reference
20
+ ├── tui/ # Terminal UI documentation
21
+ ├── useful_tools/ # Pre-built tools you can use
22
+ └── useful_plugins/ # Claude Code plugins and extensions
23
+ ```
24
+
25
+ **Start here:** `quickstart.md` for a 60-second intro, then use this README for comprehensive reference.
26
+
27
+ ---
28
+
29
+ ## Context for AI Assistants
30
+
31
+ You are helping a developer who wants to use ConnectOnion, a Python framework for creating AI agents with behavior tracking. This document contains everything you need to help them write effective ConnectOnion code.
32
+
33
+ **Key Principles:**
34
+ - Keep simple things simple, make hard things possible
35
+ - Function-based tools are preferred over classes
36
+ - **For class-based tools: Pass instances directly (not individual methods)**
37
+ - Activity logging to .co/logs/ (Python SDK only)
38
+ - Default settings work for most use cases
39
+
40
+ ---
41
+
42
+ ## What is ConnectOnion?
43
+
44
+ ConnectOnion is a simple Python framework for creating AI agents that can use tools and track their behavior. Think of it as a way to build ChatGPT-like agents with custom tools.
45
+
46
+ **Core Features:**
47
+ - Turn regular Python functions into agent tools automatically
48
+ - Control agent behavior with max_iterations parameter
49
+ - Automatic behavior tracking and history
50
+ - System prompts for agent personality
51
+ - Built-in OpenAI integration
52
+ - Interactive debugging with @xray and agent.auto_debug()
53
+
54
+ ---
55
+
56
+ ## Installation & Setup
57
+
58
+ ```bash
59
+ pip install connectonion
60
+ ```
61
+
62
+ **Environment Setup:**
63
+ ```bash
64
+ export OPENAI_API_KEY="your-api-key-here"
65
+ # Or use .env file
66
+ ```
67
+
68
+ ---
69
+
70
+ ## CLI Reference - Quick Project Setup
71
+
72
+ ConnectOnion includes a CLI for quickly scaffolding agent projects.
73
+
74
+ ### Installation
75
+ The CLI is automatically installed with ConnectOnion:
76
+ ```bash
77
+ pip install connectonion
78
+ # Provides two commands: 'co' and 'connectonion'
79
+ ```
80
+
81
+ ### Initialize a Project
82
+
83
+ ```bash
84
+ # Create meta-agent (default) - ConnectOnion development assistant
85
+ mkdir meta-agent
86
+ cd meta-agent
87
+ co init
88
+
89
+ # Create web automation agent
90
+ mkdir playwright-agent
91
+ cd playwright-agent
92
+ co init --template playwright
93
+ ```
94
+
95
+ ### CLI Options
96
+
97
+ - `co init` - Initialize a new agent project
98
+ - `--template, -t` - Choose template: `meta-agent` (default), `playwright`, `basic` (alias)
99
+ - `--with-examples` - Include additional example tools
100
+ - `--force` - Overwrite existing files
101
+
102
+ ### What Gets Created
103
+
104
+ ```
105
+ my-project/
106
+ ├── agent.py # Main agent implementation
107
+ ├── prompt.md # System prompt (markdown)
108
+ ├── .env.example # Environment variables template
109
+ ├── .co/ # ConnectOnion metadata
110
+ │ ├── config.toml # Project configuration
111
+ │ └── docs/
112
+ │ └── connectonion.md # Embedded framework documentation
113
+ └── .gitignore # Git ignore rules (if in git repo)
114
+ ```
115
+
116
+ ### Available Templates
117
+
118
+ **Meta-Agent (Default)** - ConnectOnion development assistant with built-in tools:
119
+ - `answer_connectonion_question()` - Expert answers from embedded docs
120
+ - `create_agent_from_template()` - Generate complete agent code
121
+ - `generate_tool_code()` - Create tool functions
122
+ - `create_test_for_agent()` - Generate pytest test suites
123
+ - `think()` - Self-reflection to analyze task completion
124
+ - `generate_todo_list()` - Create structured plans (uses GPT-4o-mini)
125
+ - `suggest_project_structure()` - Architecture recommendations
126
+
127
+ **Playwright Template** - Web automation with stateful browser control:
128
+ - `start_browser()` - Launch browser instance
129
+ - `navigate()` - Go to URLs
130
+ - `scrape_content()` - Extract page content
131
+ - `fill_form()` - Fill and submit forms
132
+ - `take_screenshot()` - Capture pages
133
+ - `extract_links()` - Get all links
134
+ - `execute_javascript()` - Run JS code
135
+ - `close_browser()` - Clean up resources
136
+
137
+ Note: Playwright template requires `pip install playwright && playwright install`
138
+
139
+ ### Interactive Features
140
+
141
+ The CLI will:
142
+ - Warn if you're in a special directory (home, root, system)
143
+ - Ask for confirmation if the directory is not empty
144
+ - Automatically detect git repositories and update `.gitignore`
145
+ - Provide clear next steps after initialization
146
+
147
+ ### Quick Start After Init
148
+
149
+ ```bash
150
+ # 1. Copy environment template
151
+ cp .env.example .env
152
+
153
+ # 2. Add your OpenAI API key to .env
154
+ echo "OPENAI_API_KEY=sk-your-key-here" > .env
155
+
156
+ # 3. Run your agent
157
+ python agent.py
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Quick Start Template
163
+
164
+ ```python
165
+ from connectonion import Agent
166
+
167
+ # 1. Define tools as regular functions
168
+ def search(query: str) -> str:
169
+ """Search for information."""
170
+ return f"Found information about {query}"
171
+
172
+ def calculate(expression: str) -> float:
173
+ """Perform mathematical calculations."""
174
+ return eval(expression) # Use safely in production
175
+
176
+ # 2. Create agent
177
+ agent = Agent(
178
+ name="my_assistant",
179
+ system_prompt="You are a helpful assistant.",
180
+ tools=[search, calculate]
181
+ # max_iterations=10 (default)
182
+ )
183
+
184
+ # 3. Use agent
185
+ result = agent.input("What is 25 * 4?")
186
+ print(result)
187
+ ```
188
+
189
+ **Example output (will vary):**
190
+
191
+ ```
192
+ 100
193
+ ```
194
+
195
+ ---
196
+
197
+ ## How ConnectOnion Works - The Agent Loop
198
+
199
+ ### Input → Processing → Output Flow
200
+
201
+ ```python
202
+ # 1. User provides input
203
+ result = agent.input("Search for Python tutorials and summarize them")
204
+
205
+ # 2. Agent processes in iterations:
206
+ # Iteration 1: LLM decides → "I need to search first"
207
+ # → Calls search("Python tutorials")
208
+ # → Gets result: "Found 10 tutorials about Python"
209
+
210
+ # Iteration 2: LLM continues → "Now I need to summarize"
211
+ # → Calls summarize("Found 10 tutorials...")
212
+ # → Gets result: "Summary: Python tutorials cover..."
213
+
214
+ # Iteration 3: LLM concludes → "Task complete"
215
+ # → Returns final answer (no more tool calls)
216
+
217
+ # 3. User gets final result
218
+ print(result) # "Here's a summary of Python tutorials: ..."
219
+ ```
220
+
221
+ ### The Agent Execution Loop
222
+
223
+ Each `agent.input()` call follows this pattern:
224
+
225
+ 1. **Setup**: Agent receives user prompt + system prompt
226
+ 2. **Loop** (up to `max_iterations` times):
227
+ - Send current conversation to LLM
228
+ - If LLM returns tool calls → execute them → add results to conversation
229
+ - If LLM returns text only → task complete, exit loop
230
+ 3. **Return**: Final LLM response to user
231
+
232
+ ### Message Flow Example
233
+
234
+ ```python
235
+ # Internal conversation that builds up:
236
+
237
+ # Initial messages
238
+ [
239
+ {"role": "system", "content": "You are a helpful assistant..."},
240
+ {"role": "user", "content": "Search for Python tutorials and summarize"}
241
+ ]
242
+
243
+ # After iteration 1 (LLM called search tool)
244
+ [
245
+ {"role": "system", "content": "You are a helpful assistant..."},
246
+ {"role": "user", "content": "Search for Python tutorials and summarize"},
247
+ {"role": "assistant", "tool_calls": [{"name": "search", "arguments": {"query": "Python tutorials"}}]},
248
+ {"role": "tool", "content": "Found 10 tutorials about Python basics...", "tool_call_id": "call_1"}
249
+ ]
250
+
251
+ # After iteration 2 (LLM called summarize tool)
252
+ [
253
+ # ... previous messages ...
254
+ {"role": "assistant", "tool_calls": [{"name": "summarize", "arguments": {"text": "Found 10 tutorials..."}}]},
255
+ {"role": "tool", "content": "Summary: Python tutorials cover variables, functions...", "tool_call_id": "call_2"}
256
+ ]
257
+
258
+ # Final iteration (LLM provides answer)
259
+ [
260
+ # ... previous messages ...
261
+ {"role": "assistant", "content": "Here's a summary of Python tutorials: They cover..."}
262
+ ]
263
+ ```
264
+
265
+ ### Input/Output Types
266
+
267
+ **Input to `agent.input()`:**
268
+ - `prompt` (str): User's request/question
269
+ - `max_iterations` (optional int): Override iteration limit for this request
270
+
271
+ **Output from `agent.input()`:**
272
+ - String: Final LLM response to user
273
+ - If max iterations reached: `"Task incomplete: Maximum iterations (N) reached."`
274
+
275
+ **Tool Function Signatures:**
276
+ ```python
277
+ # Tools always follow this pattern:
278
+ def tool_name(param1: type, param2: type = default) -> return_type:
279
+ """Description for LLM."""
280
+ # Your logic here
281
+ return result # Must match return_type
282
+ ```
283
+
284
+ ### Automatic Behavior Tracking
285
+
286
+ Every `agent.input()` call creates a record:
287
+
288
+ ```python
289
+ # Automatic tracking in ~/.connectonion/agents/{name}/behavior.json
290
+ {
291
+ "timestamp": "2024-01-15T10:30:00",
292
+ "user_prompt": "Search for Python tutorials and summarize",
293
+ "tool_calls": [
294
+ {
295
+ "name": "search",
296
+ "arguments": {"query": "Python tutorials"},
297
+ "result": "Found 10 tutorials...",
298
+ "status": "success",
299
+ "timing": 245.3 # milliseconds
300
+ },
301
+ {
302
+ "name": "summarize",
303
+ "arguments": {"text": "Found 10 tutorials..."},
304
+ "result": "Summary: Python tutorials...",
305
+ "status": "success",
306
+ "timing": 156.7
307
+ }
308
+ ],
309
+ "result": "Here's a summary of Python tutorials...",
310
+ "duration": 2.34 # total seconds
311
+ }
312
+
313
+ # Access history
314
+ print(agent.history.summary()) # Human-readable summary
315
+ print(len(agent.history.records)) # Number of tasks completed
316
+ ```
317
+
318
+ ---
319
+
320
+ ## Core API Reference
321
+
322
+ ### Agent Class
323
+
324
+ ```python
325
+ class Agent:
326
+ def __init__(
327
+ self,
328
+ name: str,
329
+ llm: Optional[LLM] = None,
330
+ tools: Optional[List[Callable]] = None,
331
+ system_prompt: Union[str, Path, None] = None,
332
+ api_key: Optional[str] = None,
333
+ model: str = "gpt-4-mini",
334
+ max_iterations: int = 10
335
+ )
336
+
337
+ def input(self, prompt: str, max_iterations: Optional[int] = None) -> str:
338
+ """Send input to agent and get response."""
339
+
340
+ def add_tool(self, tool: Callable):
341
+ """Add a new tool to the agent."""
342
+
343
+ def remove_tool(self, tool_name: str) -> bool:
344
+ """Remove a tool by name."""
345
+
346
+ def list_tools(self) -> List[str]:
347
+ """List all available tool names."""
348
+ ```
349
+
350
+ ### Key Parameters Explained
351
+
352
+ **max_iterations** (Default: 10):
353
+ - Controls how many tool calls the agent can make per task
354
+ - Simple tasks: 3-5 iterations
355
+ - Standard workflows: 10-15 iterations
356
+ - Complex analysis: 20-40 iterations
357
+ - Research projects: 30-50 iterations
358
+
359
+ **system_prompt** (Recommended: Use markdown files):
360
+ - **Path/str: Load from file (RECOMMENDED)** - Keep prompts separate from code
361
+ - String: Direct prompt text (only for very simple cases)
362
+ - None: Uses default helpful assistant prompt
363
+
364
+ ---
365
+
366
+ ## Function-Based Tools (Recommended Approach)
367
+
368
+ ### Basic Tool Creation
369
+
370
+ ```python
371
+ def my_tool(param: str, optional_param: int = 10) -> str:
372
+ """This docstring becomes the tool description."""
373
+ return f"Processed {param} with value {optional_param}"
374
+
375
+ # Automatic conversion - just pass the function!
376
+ agent = Agent("assistant", tools=[my_tool])
377
+ ```
378
+
379
+ ### Tool Guidelines
380
+
381
+ **Type Hints are Required:**
382
+ ```python
383
+ # Good - clear types
384
+ def search(query: str, limit: int = 10) -> str:
385
+ return f"Found {limit} results for {query}"
386
+
387
+ # Bad - no type hints
388
+ def search(query, limit=10):
389
+ return f"Found {limit} results for {query}"
390
+ ```
391
+
392
+ **Docstrings Become Descriptions:**
393
+ ```python
394
+ def analyze_data(data: str, method: str = "standard") -> str:
395
+ """Analyze data using specified method.
396
+
397
+ Methods: standard, detailed, quick
398
+ """
399
+ return f"Analysis complete using {method} method"
400
+ ```
401
+
402
+ ### Tool Descriptions and Schemas (What the LLM Sees)
403
+
404
+ The first line of a tool's docstring is used as the human‑readable description. ConnectOnion also builds a JSON schema from the function signature and type hints.
405
+
406
+ ```python
407
+ from typing import Literal, Annotated
408
+
409
+ Priority = Literal["low", "normal", "high"]
410
+
411
+ def create_ticket(
412
+ title: str,
413
+ description: str,
414
+ priority: Priority = "normal",
415
+ assignee: Annotated[str, "email"] | None = None,
416
+ ) -> str:
417
+ """Create a ticket and return its ID."""
418
+ return "T-1024"
419
+
420
+ # Internally, the agent exposes a schema like this to the LLM:
421
+ schema = {
422
+ "name": "create_ticket",
423
+ "description": "Create a ticket and return its ID.",
424
+ "parameters": {
425
+ "type": "object",
426
+ "properties": {
427
+ "title": {"type": "string"},
428
+ "description": {"type": "string"},
429
+ "priority": {"enum": ["low", "normal", "high"]},
430
+ "assignee": {"type": "string"}
431
+ },
432
+ "required": ["title", "description"]
433
+ }
434
+ }
435
+ ```
436
+
437
+ Best practices for descriptions:
438
+
439
+ - Start with a concise, imperative one‑liner: “Create…”, “Search…”, “Summarize…”.
440
+ - Mention key constraints and side effects (“Sends network request”, “Writes to disk”).
441
+ - Clarify required vs optional parameters and valid ranges/enums.
442
+ - Prefer deterministic behavior; if not, state what is non‑deterministic.
443
+ - Keep the first line under ~90 characters; add additional details on following lines.
444
+
445
+ ---
446
+
447
+ ## Stateful Tools with Playwright (Shared Context via Classes)
448
+
449
+ **✅ RECOMMENDED: Pass the class instance directly to ConnectOnion!**
450
+
451
+ ConnectOnion automatically discovers all public methods with type hints when you pass a class instance. This is much cleaner than listing methods individually.
452
+
453
+ Use a class instance when tools need to share state (browser, cache, DB handles). You can also mix class methods with regular function tools.
454
+
455
+ Prerequisites:
456
+
457
+ ```bash
458
+ pip install playwright
459
+ playwright install
460
+ ```
461
+
462
+ ```python
463
+ from connectonion import Agent
464
+
465
+ try:
466
+ from playwright.sync_api import sync_playwright
467
+ except ImportError:
468
+ raise SystemExit("Install Playwright: pip install playwright && playwright install")
469
+
470
+
471
+ class BrowserAutomation:
472
+ """Real browser session with shared context across tool calls."""
473
+
474
+ def __init__(self):
475
+ self._p = None
476
+ self._browser = None
477
+ self._page = None
478
+ self._screenshots: list[str] = []
479
+
480
+ def start_browser(self, headless: bool = True) -> str:
481
+ """Start a Chromium browser session."""
482
+ self._p = sync_playwright().start()
483
+ self._browser = self._p.chromium.launch(headless=headless)
484
+ self._page = self._browser.new_page()
485
+ return f"Browser started (headless={headless})"
486
+
487
+ def goto(self, url: str) -> str:
488
+ """Navigate to a URL and return the page title."""
489
+ if not self._page:
490
+ return "Error: Browser not started"
491
+ self._page.goto(url)
492
+ return self._page.title()
493
+
494
+ def screenshot(self, filename: str = "page.png") -> str:
495
+ """Save a screenshot and return the filename."""
496
+ if not self._page:
497
+ return "Error: Browser not started"
498
+ self._page.screenshot(path=filename)
499
+ self._screenshots.append(filename)
500
+ return filename
501
+
502
+ def close(self) -> str:
503
+ """Close resources and end the session."""
504
+ try:
505
+ if self._page:
506
+ self._page.close()
507
+ if self._browser:
508
+ self._browser.close()
509
+ if self._p:
510
+ self._p.stop()
511
+ return "Browser closed"
512
+ finally:
513
+ self._page = None
514
+ self._browser = None
515
+ self._p = None
516
+
517
+
518
+ def format_title(title: str) -> str:
519
+ """Format a page title for logs or UIs."""
520
+ return f"[PAGE] {title}"
521
+
522
+
523
+ # ✅ BEST PRACTICE: Pass class instances directly!
524
+ # ConnectOnion automatically extracts all public methods as tools
525
+ browser = BrowserAutomation()
526
+ agent = Agent(
527
+ name="web_assistant",
528
+ tools=[browser, format_title], # Mix class instance + functions
529
+ system_prompt="You are a web automation assistant. Be explicit about each step."
530
+ )
531
+
532
+ # Manual session (no LLM) — call tools directly
533
+ print(agent.tools.start_browser.run(headless=True))
534
+ title = agent.tools.goto.run("https://example.com")
535
+ print(agent.tools.format_title.run(title=title))
536
+ print(agent.tools.screenshot.run(filename="example.png"))
537
+ print(agent.tools.close.run())
538
+ ```
539
+
540
+ **Example output:**
541
+
542
+ ```
543
+ Browser started (headless=True)
544
+ [PAGE] Example Domain
545
+ example.png
546
+ Browser closed
547
+ ```
548
+
549
+ Agent‑driven session (LLM decides which tools to call):
550
+
551
+ ```python
552
+ # Natural language instruction — the agent chooses and orders tool calls
553
+ result = agent.input(
554
+ """
555
+ Open https://example.com, return the page title, take a screenshot named
556
+ example.png, then close the browser.
557
+ """
558
+ )
559
+ print(result)
560
+ ```
561
+
562
+ **Example output (simplified):**
563
+
564
+ ```
565
+ Title: Example Domain
566
+ Screenshot saved: example.png
567
+ Browser session closed.
568
+ ```
569
+
570
+ Why this pattern works:
571
+
572
+ - Class instance keeps shared state (browser/page) across calls.
573
+ - Function tools are great for lightweight utilities (formatting, parsing, saving records).
574
+ - The agent exposes both as callable tools with proper schemas and docstring descriptions.
575
+
576
+ ---
577
+
578
+ ## max_iterations Control
579
+
580
+ ### Basic Usage
581
+
582
+ ```python
583
+ # Default: 10 iterations (good for most tasks)
584
+ agent = Agent("helper", tools=[...])
585
+
586
+ # Simple tasks - fewer iterations
587
+ calc_agent = Agent("calculator", tools=[calculate], max_iterations=5)
588
+
589
+ # Complex tasks - more iterations
590
+ research_agent = Agent("researcher", tools=[...], max_iterations=25)
591
+ ```
592
+
593
+ ### Per-Request Override
594
+
595
+ ```python
596
+ agent = Agent("flexible", tools=[...])
597
+
598
+ # Normal task
599
+ result = agent.input("Simple question")
600
+
601
+ # Complex task needs more iterations
602
+ result = agent.input(
603
+ "Analyze all data and generate comprehensive report",
604
+ max_iterations=30
605
+ )
606
+ ```
607
+
608
+ ### When You Hit the Limit
609
+
610
+ ```python
611
+ # Error message when limit reached:
612
+ "Task incomplete: Maximum iterations (10) reached."
613
+
614
+ # Solutions:
615
+ # 1. Increase agent's default
616
+ agent.max_iterations = 20
617
+
618
+ # 2. Override for specific task
619
+ result = agent.input("complex task", max_iterations=25)
620
+
621
+ # 3. Break task into smaller parts
622
+ result1 = agent.input("First analyze the data")
623
+ result2 = agent.input(f"Based on {result1}, create summary")
624
+ ```
625
+
626
+ ---
627
+
628
+ ## System Prompts & Personality
629
+
630
+ **Best Practice: Use Markdown Files for System Prompts**
631
+
632
+ Keep your prompts separate from code for better maintainability, version control, and collaboration.
633
+
634
+ ### Recommended: Load from Markdown File
635
+
636
+ ```python
637
+ # ✅ RECOMMENDED: Load from markdown file
638
+ agent = Agent(
639
+ name="support_agent",
640
+ system_prompt="prompts/customer_support.md", # Clean separation
641
+ tools=[...]
642
+ )
643
+
644
+ # Using Path object (also good)
645
+ from pathlib import Path
646
+ agent = Agent(
647
+ name="data_analyst",
648
+ system_prompt=Path("prompts") / "data_analyst.md",
649
+ tools=[...]
650
+ )
651
+
652
+ # Any extension works (.md, .txt, .prompt, etc.)
653
+ agent = Agent(
654
+ name="coder",
655
+ system_prompt="prompts/senior_developer.txt",
656
+ tools=[...]
657
+ )
658
+ ```
659
+
660
+ ### Example Prompt File (`prompts/customer_support.md`)
661
+
662
+ ```markdown
663
+ # Customer Support Agent
664
+
665
+ You are a senior customer support specialist with 10+ years of experience.
666
+
667
+ ## Your Expertise
668
+ - Empathetic communication with frustrated customers
669
+ - Root cause analysis for technical issues
670
+ - Clear, step-by-step problem solving
671
+ - Escalation management
672
+
673
+ ## Guidelines
674
+ 1. **Always acknowledge** the customer's concern first
675
+ 2. **Ask clarifying questions** to understand the real problem
676
+ 3. **Provide actionable solutions** with clear next steps
677
+ 4. **Follow up** to ensure satisfaction
678
+
679
+ ## Tone
680
+ - Professional but warm
681
+ - Patient and understanding
682
+ - Confident in your recommendations
683
+ - Never dismissive of concerns
684
+
685
+ ## Example Responses
686
+ When a customer is frustrated:
687
+ > "I completely understand your frustration with this issue. Let me help you resolve this right away. Can you tell me exactly what happened when you tried to [action]?"
688
+ ```
689
+
690
+ ### Why Markdown Files Are Better
691
+
692
+ **✅ Advantages:**
693
+ - **Version Control**: Track prompt changes over time
694
+ - **Collaboration**: Team members can easily review and edit prompts
695
+ - **Readability**: Markdown formatting makes prompts clear and professional
696
+ - **Reusability**: Share prompts across different agents
697
+ - **No Code Pollution**: Keep business logic separate from implementation
698
+ - **IDE Support**: Syntax highlighting and formatting in markdown files
699
+
700
+ **❌ Avoid Inline Strings:**
701
+ ```python
702
+ # ❌ DON'T DO THIS - Hard to maintain
703
+ agent = Agent(
704
+ name="support",
705
+ system_prompt="You are a customer support agent. Be helpful and friendly. Always ask follow-up questions. Use empathetic language. Provide step-by-step solutions...", # This gets messy!
706
+ tools=[...]
707
+ )
708
+ ```
709
+
710
+ ### Advanced Prompt Organization
711
+
712
+ ```python
713
+ # Organize prompts by role/domain
714
+ prompts/
715
+ ├── customer_support/
716
+ │ ├── tier1_support.md
717
+ │ ├── technical_support.md
718
+ │ └── billing_support.md
719
+ ├── data_analysis/
720
+ │ ├── financial_analyst.md
721
+ │ └── research_analyst.md
722
+ └── development/
723
+ ├── code_reviewer.md
724
+ └── senior_developer.md
725
+
726
+ # Load specific prompts
727
+ support_agent = Agent(
728
+ name="tier1_support",
729
+ system_prompt="prompts/customer_support/tier1_support.md",
730
+ tools=[create_ticket, search_kb, escalate]
731
+ )
732
+
733
+ analyst_agent = Agent(
734
+ name="financial_analyst",
735
+ system_prompt="prompts/data_analysis/financial_analyst.md",
736
+ tools=[fetch_data, analyze_trends, generate_report]
737
+ )
738
+ ```
739
+
740
+ ### Simple Cases Only
741
+
742
+ For very simple, single-line prompts, inline strings are acceptable:
743
+
744
+ ```python
745
+ # ✅ OK for simple cases
746
+ calculator = Agent(
747
+ name="calc",
748
+ system_prompt="You are a helpful calculator. Always show your work step by step.",
749
+ tools=[calculate]
750
+ )
751
+ ```
752
+
753
+ ---
754
+
755
+ ## Debugging with @xray
756
+
757
+ Debug your agent's tool execution with real-time insights - see what your AI agent is thinking.
758
+
759
+ ### Quick Start
760
+
761
+ ```python
762
+ from connectonion.decorators import xray
763
+
764
+ @xray
765
+ def my_tool(text: str) -> str:
766
+ """Process some text."""
767
+
768
+ # Now you can see inside the agent's mind!
769
+ print(xray.agent.name) # "my_assistant"
770
+ print(xray.task) # "Process this document"
771
+ print(xray.iteration) # 1, 2, 3...
772
+
773
+ return f"Processed: {text}"
774
+ ```
775
+
776
+ That's it! Add `@xray` to any tool to unlock debugging superpowers.
777
+
778
+ ### What You Can Access
779
+
780
+ Inside any `@xray` decorated function:
781
+
782
+ ```python
783
+ xray.agent # The Agent instance calling this tool
784
+ xray.task # Original request from user
785
+ xray.messages # Full conversation history
786
+ xray.iteration # Which round of tool calls (1-10)
787
+ xray.previous_tools # Tools called before this one
788
+ ```
789
+
790
+ ### Real Example
791
+
792
+ ```python
793
+ @xray
794
+ def search_database(query: str) -> str:
795
+ """Search our database."""
796
+
797
+ # See what led to this search
798
+ print(f"User asked: {xray.task}")
799
+ print(f"This is iteration {xray.iteration}")
800
+
801
+ if xray.previous_tools:
802
+ print(f"Already tried: {xray.previous_tools}")
803
+
804
+ # Adjust behavior based on context
805
+ if xray.iteration > 2:
806
+ return "No results found, please refine your search"
807
+
808
+ return f"Found 5 results for '{query}'"
809
+ ```
810
+
811
+ ### Visual Execution Trace
812
+
813
+ See the complete flow of your agent's work from inside a tool:
814
+
815
+ ```python
816
+ @xray
817
+ def analyze_data(text: str) -> str:
818
+ """Analyze data and show execution trace."""
819
+
820
+ # Show what happened so far
821
+ xray.trace()
822
+
823
+ return "Analysis complete"
824
+ ```
825
+
826
+ **Output:**
827
+ ```
828
+ Task: "Find Python tutorials and summarize them"
829
+
830
+ [1] • 89ms search_database(query="Python tutorials")
831
+ IN → query: "Python tutorials"
832
+ OUT ← "Found 5 results for 'Python tutorials'"
833
+
834
+ [2] • 234ms summarize_text(text="Found 5 results...", max_words=50)
835
+ IN → text: "Found 5 results for 'Python tutorials'"
836
+ IN → max_words: 50
837
+ OUT ← "5 Python tutorials found covering basics to advanced topics"
838
+
839
+ Total: 323ms • 2 steps • 1 iterations
840
+ ```
841
+
842
+ ### Debug in Your IDE
843
+
844
+ Set a breakpoint and explore:
845
+
846
+ ```python
847
+ @xray
848
+ def analyze_sentiment(text: str) -> str:
849
+ # 🎯 Set breakpoint on next line
850
+ sentiment = "positive" # When stopped here in debugger:
851
+ # >>> xray
852
+ # <XrayContext active>
853
+ # agent: 'my_bot'
854
+ # task: 'How do people feel about Python?'
855
+ # >>> xray.messages
856
+ # [{'role': 'user', 'content': '...'}, ...]
857
+
858
+ return sentiment
859
+ ```
860
+
861
+ ### Practical Use Cases
862
+
863
+ **1. Understand Why a Tool Was Called**
864
+ ```python
865
+ @xray
866
+ def emergency_shutdown():
867
+ """Shutdown the system."""
868
+
869
+ # Check why this drastic action was requested
870
+ print(f"Shutdown requested because: {xray.task}")
871
+ print(f"After trying: {xray.previous_tools}")
872
+
873
+ # Maybe don't shutdown if it's the first try
874
+ if xray.iteration == 1:
875
+ return "Try restarting first"
876
+
877
+ return "System shutdown complete"
878
+ ```
879
+
880
+ **2. Adaptive Tool Behavior**
881
+ ```python
882
+ @xray
883
+ def fetch_data(source: str) -> str:
884
+ """Fetch data from a source."""
885
+
886
+ # Use cache on repeated calls
887
+ if "fetch_data" in xray.previous_tools:
888
+ return "Using cached data"
889
+
890
+ # Fresh fetch on first call
891
+ return f"Fresh data from {source}"
892
+ ```
893
+
894
+ **3. Debug Complex Flows**
895
+ ```python
896
+ @xray
897
+ def process_order(order_id: str) -> str:
898
+ """Process an order."""
899
+
900
+ # See the full context when debugging
901
+ if xray.agent:
902
+ print(f"Processing for agent: {xray.agent.name}")
903
+ print(f"Original request: {xray.task}")
904
+ print(f"Conversation length: {len(xray.messages)}")
905
+
906
+ return f"Order {order_id} processed"
907
+ ```
908
+
909
+ ### Tips
910
+
911
+ 1. **Development Only** - Remove @xray in production for best performance
912
+ 2. **Combine with IDE** - Set breakpoints for interactive debugging
913
+ 3. **Use trace()** - Call `xray.trace()` to see full execution flow
914
+ 4. **Check context** - Always verify `xray.agent` exists before using
915
+
916
+ ### Common Patterns
917
+
918
+ **Logging What Matters:**
919
+ ```python
920
+ @xray
921
+ def important_action(data: str) -> str:
922
+ # Log with context
923
+ if xray.agent:
924
+ logger.info(f"Agent {xray.agent.name} performing action")
925
+ logger.info(f"Original task: {xray.task}")
926
+ logger.info(f"Iteration: {xray.iteration}")
927
+
928
+ return "Action completed"
929
+ ```
930
+
931
+ **Conditional Logic:**
932
+ ```python
933
+ @xray
934
+ def smart_search(query: str) -> str:
935
+ # Different strategies based on context
936
+ if xray.iteration > 1:
937
+ # Broaden search on retry
938
+ query = f"{query} OR related"
939
+
940
+ if "analyze" in xray.previous_tools:
941
+ # We already analyzed, search differently
942
+ query = f"summary of {query}"
943
+
944
+ return f"Results for: {query}"
945
+ ```
946
+
947
+ ---
948
+
949
+ ## Interactive Debugging with agent.auto_debug()
950
+
951
+ Debug your agents interactively - pause at breakpoints, inspect variables, and modify behavior in real-time.
952
+
953
+ ### Quick Start
954
+
955
+ ```python
956
+ from connectonion import Agent
957
+ from connectonion.decorators import xray
958
+
959
+ @xray # Tools with @xray become breakpoints
960
+ def search(query: str):
961
+ return f"Results for {query}"
962
+
963
+ agent = Agent("assistant", tools=[search])
964
+ agent.auto_debug() # Enable interactive debugging
965
+
966
+ # Agent will pause at @xray tools
967
+ agent.input("Search for Python tutorials")
968
+ ```
969
+
970
+ ### What Happens at Breakpoints
971
+
972
+ When execution pauses, you'll see:
973
+ ```
974
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
975
+ @xray BREAKPOINT: search
976
+
977
+ Local Variables:
978
+ query = "Python tutorials"
979
+ result = "Results for Python tutorials"
980
+
981
+ What do you want to do?
982
+ → Continue execution 🚀 [c or Enter]
983
+ Edit values 🔍 [e]
984
+ Quit debugging 🚫 [q]
985
+ >
986
+ ```
987
+
988
+ ### Debug Menu Commands
989
+
990
+ - **Continue** (`c` or Enter): Resume execution
991
+ - **Edit** (`e`): Open Python REPL to modify variables
992
+ - **Quit** (`q`): Stop debugging
993
+
994
+ ### Edit Values in Python REPL
995
+
996
+ ```python
997
+ > e
998
+
999
+ >>> # See current values
1000
+ >>> query
1001
+ 'Python tutorials'
1002
+
1003
+ >>> # Modify them
1004
+ >>> query = "Python advanced tutorials"
1005
+ >>> result = search(query)
1006
+
1007
+ >>> # Continue with changes
1008
+ >>> /continue
1009
+ ```
1010
+
1011
+ ### Use Cases
1012
+
1013
+ **1. Test "What If" Scenarios:**
1014
+ ```python
1015
+ @xray
1016
+ def calculate_price(quantity: int):
1017
+ return quantity * 10
1018
+
1019
+ agent.auto_debug()
1020
+ agent.input("Calculate price for 5 items")
1021
+
1022
+ # At breakpoint:
1023
+ # > e
1024
+ # >>> quantity = 100 # Test bulk pricing
1025
+ # >>> /continue
1026
+ ```
1027
+
1028
+ **2. Debug Wrong Decisions:**
1029
+ ```python
1030
+ @xray
1031
+ def search_contacts(name: str):
1032
+ # Agent searched for "Jon" but database has "John"
1033
+ contacts = {"John": "john@email.com"}
1034
+ return contacts.get(name, "Not found")
1035
+
1036
+ agent.auto_debug()
1037
+ agent.input("Email Jon about meeting")
1038
+
1039
+ # At breakpoint:
1040
+ # > e
1041
+ # >>> name = "John" # Fix typo
1042
+ # >>> result = search_contacts(name)
1043
+ # >>> /continue
1044
+ ```
1045
+
1046
+ **3. Understand Agent Behavior:**
1047
+ ```python
1048
+ # Just press 'c' at each breakpoint to see:
1049
+ # - What tools are called
1050
+ # - What parameters are used
1051
+ # - What results are returned
1052
+ # Perfect for learning how your agent works!
1053
+ ```
1054
+
1055
+ ### Tips
1056
+
1057
+ - **Development only**: Use `auto_debug()` during development, not production
1058
+ - **Combine with @xray**: Mark critical tools with `@xray` for breakpoints
1059
+ - **Press 'c' to skip**: If you just want to observe, press 'c' at each pause
1060
+ - **Full Python access**: In edit mode, you have full Python REPL access
1061
+
1062
+ For more details, see [docs/auto_debug.md](https://github.com/openonion/connectonion/blob/main/docs/auto_debug.md)
1063
+
1064
+ ---
1065
+
1066
+ ## Common Patterns & Examples
1067
+
1068
+ ### Pattern 1: Simple Calculator Bot
1069
+
1070
+ ```python
1071
+ def calculate(expression: str) -> float:
1072
+ """Perform mathematical calculations."""
1073
+ try:
1074
+ # Safe eval for demo - use proper parsing in production
1075
+ allowed = "0123456789+-*/(). "
1076
+ if all(c in allowed for c in expression):
1077
+ return eval(expression)
1078
+ else:
1079
+ raise ValueError("Invalid characters")
1080
+ except Exception as e:
1081
+ raise ValueError(f"Calculation error: {e}")
1082
+
1083
+ calc_agent = Agent(
1084
+ name="calculator",
1085
+ system_prompt="You are a helpful calculator. Always show your work.",
1086
+ tools=[calculate],
1087
+ max_iterations=5 # Math rarely needs many iterations
1088
+ )
1089
+
1090
+ result = calc_agent.input("What is (25 + 15) * 3?")
1091
+ ```
1092
+
1093
+ ### Pattern 2: Research Assistant
1094
+
1095
+ ```python
1096
+ def web_search(query: str, num_results: int = 5) -> str:
1097
+ """Search the web for information."""
1098
+ # Your search implementation
1099
+ return f"Found {num_results} results for '{query}'"
1100
+
1101
+ def summarize(text: str, length: str = "medium") -> str:
1102
+ """Summarize text content."""
1103
+ # Your summarization implementation
1104
+ return f"Summary ({length}): {text[:100]}..."
1105
+
1106
+ def save_notes(content: str, filename: str = "research.txt") -> str:
1107
+ """Save content to a file."""
1108
+ # Your file saving implementation
1109
+ return f"Saved content to {filename}"
1110
+
1111
+ research_agent = Agent(
1112
+ name="researcher",
1113
+ system_prompt="You are a thorough researcher who provides well-sourced information.",
1114
+ tools=[web_search, summarize, save_notes],
1115
+ max_iterations=25 # Research involves many steps
1116
+ )
1117
+
1118
+ result = research_agent.input(
1119
+ "Research the latest developments in quantum computing and save a summary"
1120
+ )
1121
+ ```
1122
+
1123
+ ### Pattern 3: File Analyzer
1124
+
1125
+ ```python
1126
+ def read_file(filepath: str) -> str:
1127
+ """Read contents of a text file."""
1128
+ try:
1129
+ with open(filepath, 'r', encoding='utf-8') as f:
1130
+ return f.read()
1131
+ except FileNotFoundError:
1132
+ return f"Error: File {filepath} not found"
1133
+ except Exception as e:
1134
+ return f"Error reading file: {e}"
1135
+
1136
+ def analyze_text(text: str, analysis_type: str = "summary") -> str:
1137
+ """Analyze text content."""
1138
+ if analysis_type == "summary":
1139
+ return f"Text summary: {len(text)} characters, {len(text.split())} words"
1140
+ elif analysis_type == "sentiment":
1141
+ return "Sentiment analysis: Neutral tone detected"
1142
+ else:
1143
+ return f"Analysis type '{analysis_type}' not supported"
1144
+
1145
+ def generate_report(findings: str, format: str = "markdown") -> str:
1146
+ """Generate a formatted report."""
1147
+ if format == "markdown":
1148
+ return f"# Analysis Report\n\n{findings}\n\nGenerated by ConnectOnion"
1149
+ else:
1150
+ return findings
1151
+
1152
+ file_agent = Agent(
1153
+ name="file_analyzer",
1154
+ system_prompt="You are a document analyst who provides detailed insights.",
1155
+ tools=[read_file, analyze_text, generate_report],
1156
+ max_iterations=15
1157
+ )
1158
+ ```
1159
+
1160
+ ### Pattern 4: Multi-Agent Coordination
1161
+
1162
+ ```python
1163
+ # Specialized agents for different tasks
1164
+ calculator = Agent("calc", tools=[calculate], max_iterations=5)
1165
+ researcher = Agent("research", tools=[web_search, summarize], max_iterations=20)
1166
+ writer = Agent("writer", tools=[generate_report, save_notes], max_iterations=10)
1167
+
1168
+ def coordinate_agents(task: str) -> str:
1169
+ """Coordinate multiple agents for complex tasks."""
1170
+ if "calculate" in task.lower():
1171
+ return calculator.input(task)
1172
+ elif "research" in task.lower():
1173
+ return researcher.input(task)
1174
+ elif "write" in task.lower():
1175
+ return writer.input(task)
1176
+ else:
1177
+ # Default to research agent for general tasks
1178
+ return researcher.input(task)
1179
+ ```
1180
+
1181
+ ---
1182
+
1183
+ ## Advanced Patterns
1184
+
1185
+ ### Auto-Retry with Increasing Limits
1186
+
1187
+ ```python
1188
+ def smart_input(agent: Agent, prompt: str, max_retries: int = 3) -> str:
1189
+ """Automatically retry with higher iteration limits if needed."""
1190
+ limits = [10, 25, 50]
1191
+
1192
+ for i, limit in enumerate(limits):
1193
+ result = agent.input(prompt, max_iterations=limit)
1194
+ if "Maximum iterations" not in result:
1195
+ return result
1196
+ if i < max_retries - 1:
1197
+ print(f"Retrying with {limits[i+1]} iterations...")
1198
+
1199
+ return "Task too complex even with maximum iterations"
1200
+
1201
+ # Usage
1202
+ agent = Agent("adaptive", tools=[...])
1203
+ result = smart_input(agent, "Complex multi-step task")
1204
+ ```
1205
+
1206
+ ### Self-Adjusting Agent
1207
+
1208
+ ```python
1209
+ class SmartAgent:
1210
+ def __init__(self, name: str, tools: list):
1211
+ self.agent = Agent(name, tools=tools)
1212
+ self.task_patterns = {
1213
+ 'simple': (['what', 'when', 'calculate'], 5),
1214
+ 'moderate': (['analyze', 'compare', 'summarize'], 15),
1215
+ 'complex': (['research', 'comprehensive', 'detailed'], 30)
1216
+ }
1217
+
1218
+ def input(self, prompt: str) -> str:
1219
+ # Detect complexity from keywords
1220
+ max_iter = 10 # default
1221
+ prompt_lower = prompt.lower()
1222
+
1223
+ for pattern_name, (keywords, iterations) in self.task_patterns.items():
1224
+ if any(keyword in prompt_lower for keyword in keywords):
1225
+ max_iter = iterations
1226
+ break
1227
+
1228
+ return self.agent.input(prompt, max_iterations=max_iter)
1229
+
1230
+ # Usage
1231
+ smart = SmartAgent("adaptive", tools=[...])
1232
+ smart.input("What is 2+2?") # Uses 5 iterations
1233
+ smart.input("Research and analyze market trends") # Uses 30 iterations
1234
+ ```
1235
+
1236
+ ---
1237
+
1238
+ ## Send Email - Built-in Email Capability
1239
+
1240
+ ConnectOnion includes built-in email functionality that allows agents to send emails with a single line of code. No configuration, no complexity.
1241
+
1242
+ ### Quick Start
1243
+
1244
+ ```python
1245
+ from connectonion import send_email
1246
+
1247
+ # Send an email with one line
1248
+ send_email("alice@example.com", "Welcome!", "Thanks for joining us!")
1249
+ ```
1250
+
1251
+ **Result:**
1252
+ ```python
1253
+ {'success': True, 'message_id': 'msg_123', 'from': '0x1234abcd@mail.openonion.ai'}
1254
+ ```
1255
+
1256
+ ### Core Concept
1257
+
1258
+ The `send_email` function provides:
1259
+ - Simple three-parameter interface: `send_email(to, subject, message)`
1260
+ - No API keys to manage (already configured)
1261
+ - Automatic email address for every agent
1262
+ - Professional delivery with good reputation
1263
+
1264
+ ### Your Agent's Email Address
1265
+
1266
+ Every agent automatically gets an email address:
1267
+ ```
1268
+ 0x1234abcd@mail.openonion.ai
1269
+ ```
1270
+
1271
+ - Based on your public key (first 10 characters)
1272
+ - Generated during `co init` or `co create`
1273
+ - Activated with `co auth`
1274
+
1275
+ ### Email Configuration
1276
+
1277
+ Your email is stored in `.co/config.toml`:
1278
+ ```toml
1279
+ [agent]
1280
+ address = "0x04e1c4ae3c57d716383153479dae869e51e86d43d88db8dfa22fba7533f3968d"
1281
+ short_address = "0x04e1c4ae"
1282
+ email = "0x04e1c4ae@mail.openonion.ai"
1283
+ email_active = false # Becomes true after 'co auth'
1284
+ ```
1285
+
1286
+ ### Using with an Agent
1287
+
1288
+ Give your agent email capability:
1289
+
1290
+ ```python
1291
+ from connectonion import Agent, send_email
1292
+
1293
+ # Create an agent with email capability
1294
+ agent = Agent(
1295
+ "customer_support",
1296
+ tools=[send_email],
1297
+ instructions="You help users and send them email confirmations"
1298
+ )
1299
+
1300
+ # The agent can now send emails autonomously
1301
+ response = agent("Send a welcome email to alice@example.com")
1302
+ # Agent sends: send_email("alice@example.com", "Welcome!", "Thanks for joining...")
1303
+ ```
1304
+
1305
+ ### Real-World Monitoring Example
1306
+
1307
+ ```python
1308
+ from connectonion import Agent, send_email
1309
+
1310
+ def check_system_status() -> dict:
1311
+ """Check if the system is running properly."""
1312
+ cpu_usage = 95 # Simulated high CPU
1313
+ return {"status": "warning", "cpu": cpu_usage}
1314
+
1315
+ # Create monitoring agent
1316
+ monitor = Agent(
1317
+ "system_monitor",
1318
+ tools=[check_system_status, send_email],
1319
+ instructions="Monitor system health and alert admin@example.com if issues"
1320
+ )
1321
+
1322
+ # Agent checks system and sends alerts
1323
+ monitor("Check the system and alert if there are problems")
1324
+ # Agent will:
1325
+ # 1. Call check_system_status()
1326
+ # 2. See high CPU (95%)
1327
+ # 3. Call send_email("admin@example.com", "Alert: High CPU", "CPU at 95%...")
1328
+ ```
1329
+
1330
+ ### Return Values
1331
+
1332
+ **Success:**
1333
+ ```python
1334
+ {
1335
+ 'success': True,
1336
+ 'message_id': 'msg_123',
1337
+ 'from': '0x1234abcd@mail.openonion.ai'
1338
+ }
1339
+ ```
1340
+
1341
+ **Failure:**
1342
+ ```python
1343
+ {
1344
+ 'success': False,
1345
+ 'error': 'Rate limit exceeded'
1346
+ }
1347
+ ```
1348
+
1349
+ Common errors:
1350
+ - `"Rate limit exceeded"` - Hit your quota
1351
+ - `"Invalid email address"` - Check the recipient
1352
+ - `"Authentication failed"` - Token issue
1353
+
1354
+ ### Content Types
1355
+
1356
+ - **Plain text**: Just send a string
1357
+ - **HTML**: Include HTML tags, automatically detected
1358
+ - **Mixed**: HTML with plain text fallback
1359
+
1360
+ ### Quotas & Limits
1361
+
1362
+ - **Free tier**: 100 emails/month
1363
+ - **Plus tier**: 1,000 emails/month
1364
+ - **Pro tier**: 10,000 emails/month
1365
+ - Automatic rate limiting with monthly reset
1366
+
1367
+ ---
1368
+
1369
+ ## llm_do - One-shot LLM Calls & When to Use AI vs Code
1370
+
1371
+ ### Core Principle: Use LLMs for Language, Code for Logic
1372
+
1373
+ **Fundamental rule**: If a task involves understanding, generating, or transforming natural language, use an LLM. If it's deterministic computation, use code.
1374
+
1375
+ ### Quick Start with llm_do
1376
+
1377
+ ```python
1378
+ from connectonion import llm_do
1379
+ from pydantic import BaseModel
1380
+
1381
+ # Simple one-shot call
1382
+ answer = llm_do("Summarize this in one sentence: The weather today is sunny with...")
1383
+ print(answer) # "The weather is sunny today."
1384
+
1385
+ # Structured output
1386
+ class EmailDraft(BaseModel):
1387
+ subject: str
1388
+ body: str
1389
+ tone: str
1390
+
1391
+ draft = llm_do(
1392
+ "Write an email thanking the team for their hard work",
1393
+ output=EmailDraft
1394
+ )
1395
+ print(draft.subject) # "Thank You Team"
1396
+ print(draft.tone) # "appreciative"
1397
+ ```
1398
+
1399
+ ### When to Use llm_do (LLM) vs Code
1400
+
1401
+ #### ✅ Use llm_do for:
1402
+
1403
+ 1. **Natural Language Generation** - Writing emails, messages, documents
1404
+ 2. **Content Understanding & Extraction** - Parse intent, extract structured data from text
1405
+ 3. **Translation & Transformation** - Language translation, tone conversion
1406
+ 4. **Summarization & Analysis** - Summaries, sentiment analysis, insights
1407
+ 5. **Creative Tasks** - Generating names, taglines, creative content
1408
+
1409
+ #### ❌ DON'T Use llm_do for:
1410
+
1411
+ 1. **Deterministic Calculations** - Math, date arithmetic, counters
1412
+ 2. **Data Lookups** - Database queries, file searches
1413
+ 3. **Simple Formatting** - Date formats, string manipulation
1414
+ 4. **Rule-Based Logic** - Validation, regex matching, conditionals
1415
+
1416
+ ### Real-World Example: Email Manager
1417
+
1418
+ ```python
1419
+ class EmailManager:
1420
+ def draft_email(self, to: str, subject: str, context: str) -> str:
1421
+ """LLM composes, code formats."""
1422
+ class EmailDraft(BaseModel):
1423
+ subject: str
1424
+ body: str
1425
+ tone: str
1426
+
1427
+ # LLM: Natural language generation
1428
+ draft = llm_do(
1429
+ f"Write email to {to} about: {context}",
1430
+ output=EmailDraft,
1431
+ temperature=0.7
1432
+ )
1433
+
1434
+ # Code: Formatting and structure
1435
+ return f"To: {to}\nSubject: {draft.subject}\n\n{draft.body}"
1436
+
1437
+ def search_emails(self, query: str) -> List[Email]:
1438
+ """Code searches, LLM understands if needed."""
1439
+ # Code: Actual database/API call
1440
+ emails = get_emails(last=100)
1441
+
1442
+ # LLM: Only for natural language understanding
1443
+ if needs_parsing(query):
1444
+ params = llm_do(f"Parse: {query}", output=SearchParams)
1445
+ query = build_query(params)
1446
+
1447
+ # Code: Filtering logic
1448
+ return [e for e in emails if matches(e, query)]
1449
+ ```
1450
+
1451
+ ### Cost & Performance Principles
1452
+
1453
+ 1. **One-shot is cheaper than iterations** - Use llm_do for single tasks, Agent for multi-step workflows
1454
+ 2. **Always use structured output** - Pass Pydantic models to avoid parsing errors
1455
+ 3. **Cache prompts in files** - Reuse prompt files for consistency and maintainability
1456
+
1457
+ ### Prompt Management Principle
1458
+
1459
+ **If a prompt is more than 3 lines, use a separate file:**
1460
+
1461
+ ```python
1462
+ # ❌ BAD: Long inline prompts clutter code
1463
+ draft = llm_do(
1464
+ """You are a professional email writer.
1465
+ Please write a formal business email that:
1466
+ - Uses appropriate business language
1467
+ - Includes a clear subject line
1468
+ - Has proper greeting and closing
1469
+ - Is concise but thorough
1470
+ Write about: {context}""",
1471
+ output=EmailDraft
1472
+ )
1473
+
1474
+ # ✅ GOOD: Clean separation of concerns
1475
+ draft = llm_do(
1476
+ context,
1477
+ system_prompt="prompts/email_writer.md", # Loads from file
1478
+ output=EmailDraft
1479
+ )
1480
+ ```
1481
+
1482
+ ### Guidelines for Tool Design
1483
+
1484
+ When creating tools for agents, follow this pattern:
1485
+
1486
+ ```python
1487
+ def my_tool(natural_input: str) -> str:
1488
+ """Tool that combines LLM understanding with code execution."""
1489
+
1490
+ # Step 1: Use LLM to understand intent (if needed)
1491
+ if needs_understanding(natural_input):
1492
+ intent = llm_do(
1493
+ f"What does user want: {natural_input}",
1494
+ output=IntentModel
1495
+ )
1496
+
1497
+ # Step 2: Use code for the actual work
1498
+ result = perform_action(intent)
1499
+
1500
+ # Step 3: Use LLM to format response (if needed)
1501
+ if needs_natural_response(result):
1502
+ response = llm_do(
1503
+ f"Explain this result conversationally: {result}",
1504
+ temperature=0.3
1505
+ )
1506
+ return response
1507
+
1508
+ return str(result)
1509
+ ```
1510
+
1511
+ ### Summary: The Right Tool for the Right Job
1512
+
1513
+ | Task | Use LLM | Use Code | Note |
1514
+ |------|---------|----------|------|
1515
+ | Writing emails | ✅ | ❌ | Natural language generation |
1516
+ | Extracting structured data | ✅ | ❌ | **Always use llm_do with Pydantic models** |
1517
+ | Parsing JSON from text | ✅ | ❌ | **Use llm_do with output=dict or custom model** |
1518
+ | Understanding intent | ✅ | ❌ | Natural language understanding |
1519
+ | Summarizing content | ✅ | ❌ | Language comprehension |
1520
+ | Translating text | ✅ | ❌ | Language transformation |
1521
+ | Database queries | ❌ | ✅ | Structured data access |
1522
+ | Math calculations | ❌ | ✅ | Deterministic computation |
1523
+ | Format validation | ❌ | ✅ | Rule-based patterns |
1524
+ | Date filtering | ❌ | ✅ | Simple comparisons |
1525
+
1526
+ **Remember**: LLMs are powerful but expensive. Use them for what they're best at - understanding and generating natural language. Use code for everything else.
1527
+
1528
+ ---
1529
+
1530
+ ## Plugin System - Reusable Event Bundles
1531
+
1532
+ Plugins are reusable event lists that package capabilities like reflection and reasoning for use across multiple agents.
1533
+
1534
+ ### Quick Start (60 seconds)
1535
+
1536
+ ```python
1537
+ from connectonion import Agent
1538
+ from connectonion.useful_plugins import reflection, react
1539
+
1540
+ # Add built-in plugins to any agent
1541
+ agent = Agent(
1542
+ name="assistant",
1543
+ tools=[search, calculate],
1544
+ plugins=[reflection, react] # One line adds both!
1545
+ )
1546
+
1547
+ agent.input("Search for Python and calculate 15 * 8")
1548
+
1549
+ # After each tool execution:
1550
+ # 💭 We learned that Python is a popular programming language...
1551
+ # 🤔 We should next calculate 15 * 8 to complete the request.
1552
+ ```
1553
+
1554
+ ### What is a Plugin?
1555
+
1556
+ **A plugin is an event list** - just like `on_events`, but reusable across agents:
1557
+
1558
+ ```python
1559
+ from connectonion import after_tools, after_each_tool, after_llm
1560
+
1561
+ # This is a plugin (one event list)
1562
+ reflection = [after_tools(add_reflection)] # after_tools for message injection
1563
+
1564
+ # This is also a plugin (multiple events in one list)
1565
+ logger = [after_llm(log_llm), after_each_tool(log_tool)] # after_each_tool for per-tool logging
1566
+
1567
+ # Use them (plugins takes a list of plugins)
1568
+ agent = Agent("assistant", tools=[search], plugins=[reflection, logger])
1569
+ ```
1570
+
1571
+ **Just like tools:**
1572
+ - Tools: `Agent(tools=[search, calculate])`
1573
+ - Plugins: `Agent(plugins=[reflection, logger])`
1574
+
1575
+ ### Plugin vs on_events
1576
+
1577
+ The difference:
1578
+ - **on_events**: Takes one event list (custom for this agent)
1579
+ - **plugins**: Takes a list of event lists (reusable across agents)
1580
+
1581
+ ```python
1582
+ # Reusable plugin (an event list)
1583
+ logger = [after_llm(log_llm)]
1584
+
1585
+ # Use both together
1586
+ agent = Agent(
1587
+ name="assistant",
1588
+ tools=[search],
1589
+ plugins=[logger], # List of event lists
1590
+ on_events=[after_llm(add_timestamp), after_each_tool(log_tool)] # One event list
1591
+ )
1592
+ ```
1593
+
1594
+ ### Built-in Plugins (useful_plugins)
1595
+
1596
+ ConnectOnion provides ready-to-use plugins:
1597
+
1598
+ **Reflection Plugin** - Generates insights after each tool execution:
1599
+
1600
+ ```python
1601
+ from connectonion import Agent
1602
+ from connectonion.useful_plugins import reflection
1603
+
1604
+ agent = Agent("assistant", tools=[search], plugins=[reflection])
1605
+
1606
+ agent.input("Search for Python")
1607
+ # 💭 We learned that Python is a popular high-level programming language known for simplicity
1608
+ ```
1609
+
1610
+ **ReAct Plugin** - Uses ReAct-style reasoning to plan next steps:
1611
+
1612
+ ```python
1613
+ from connectonion import Agent
1614
+ from connectonion.useful_plugins import react
1615
+
1616
+ agent = Agent("assistant", tools=[search], plugins=[react])
1617
+
1618
+ agent.input("Search for Python and explain it")
1619
+ # 🤔 We learned Python is widely used. We should next explain its key features and use cases.
1620
+ ```
1621
+
1622
+ **Image Result Formatter Plugin** - Converts base64 image results to proper image messages for vision models:
1623
+
1624
+ ```python
1625
+ from connectonion import Agent
1626
+ from connectonion.useful_plugins import image_result_formatter
1627
+
1628
+ agent = Agent("assistant", tools=[take_screenshot], plugins=[image_result_formatter])
1629
+
1630
+ agent.input("Take a screenshot of the homepage and describe what you see")
1631
+ # 🖼️ Formatted tool result as image (image/png)
1632
+ # Agent can now see and analyze the actual image, not just base64 text!
1633
+ ```
1634
+
1635
+ **When to use:** Tools that return screenshots, generated images, or any visual data as base64.
1636
+ **Supported formats:** PNG, JPEG, WebP, GIF
1637
+ **What it does:** Detects base64 images in tool results and converts them to OpenAI vision API format, allowing multimodal LLMs to see images visually instead of as text.
1638
+
1639
+ **Using Multiple Plugins Together:**
1640
+
1641
+ ```python
1642
+ from connectonion import Agent
1643
+ from connectonion.useful_plugins import reflection, react, image_result_formatter
1644
+
1645
+ # Combine plugins for powerful agents
1646
+ agent = Agent(
1647
+ name="visual_researcher",
1648
+ tools=[take_screenshot, search, analyze],
1649
+ plugins=[image_result_formatter, reflection, react]
1650
+ )
1651
+
1652
+ # Now you get:
1653
+ # 🖼️ Image formatting for screenshots
1654
+ # 💭 Reflection: What we learned
1655
+ # 🤔 ReAct: What to do next
1656
+ ```
1657
+
1658
+ ### Writing Custom Plugins
1659
+
1660
+ Learn by example - here's how the reflection plugin works:
1661
+
1662
+ **Step 1: Message Compression Helper**
1663
+
1664
+ ```python
1665
+ from typing import List, Dict
1666
+
1667
+ def _compress_messages(messages: List[Dict], tool_result_limit: int = 150) -> str:
1668
+ """
1669
+ Compress conversation messages with structure:
1670
+ - USER messages → Keep FULL
1671
+ - ASSISTANT tool_calls → Keep parameters FULL
1672
+ - ASSISTANT text → Keep FULL
1673
+ - TOOL results → Truncate to tool_result_limit chars
1674
+ """
1675
+ lines = []
1676
+
1677
+ for msg in messages:
1678
+ role = msg['role']
1679
+
1680
+ if role == 'user':
1681
+ lines.append(f"USER: {msg['content']}")
1682
+
1683
+ elif role == 'assistant':
1684
+ if 'tool_calls' in msg:
1685
+ tools = [f"{tc['function']['name']}({tc['function']['arguments']})"
1686
+ for tc in msg['tool_calls']]
1687
+ lines.append(f"ASSISTANT: {', '.join(tools)}")
1688
+ else:
1689
+ lines.append(f"ASSISTANT: {msg['content']}")
1690
+
1691
+ elif role == 'tool':
1692
+ result = msg['content']
1693
+ if len(result) > tool_result_limit:
1694
+ result = result[:tool_result_limit] + '...'
1695
+ lines.append(f"TOOL: {result}")
1696
+
1697
+ return "\n".join(lines)
1698
+ ```
1699
+
1700
+ **Why this works:**
1701
+ - Keep user messages FULL (need to know what they asked)
1702
+ - Keep tool parameters FULL (exactly what actions were taken)
1703
+ - Keep assistant text FULL (reasoning/responses)
1704
+ - Truncate tool results (save tokens while maintaining overview)
1705
+
1706
+ **Step 2: Event Handler Function**
1707
+
1708
+ ```python
1709
+ from connectonion.events import after_tool
1710
+ from connectonion.llm_do import llm_do
1711
+
1712
+ def _add_reflection(agent) -> None:
1713
+ """Reflect on tool execution result"""
1714
+ trace = agent.current_session['trace'][-1]
1715
+
1716
+ if trace['type'] == 'tool_execution' and trace['status'] == 'success':
1717
+ # Extract current tool execution
1718
+ user_prompt = agent.current_session.get('user_prompt', '')
1719
+ tool_name = trace['tool_name']
1720
+ tool_args = trace['arguments']
1721
+ tool_result = trace['result']
1722
+
1723
+ # Compress conversation messages
1724
+ conversation = _compress_messages(agent.current_session['messages'])
1725
+
1726
+ # Build prompt with conversation context + current execution
1727
+ prompt = f"""CONVERSATION:
1728
+ {conversation}
1729
+
1730
+ CURRENT EXECUTION:
1731
+ User asked: {user_prompt}
1732
+ Tool: {tool_name}({tool_args})
1733
+ Result: {tool_result}
1734
+
1735
+ Reflect in 1-2 sentences on what we learned:"""
1736
+
1737
+ reflection_text = llm_do(
1738
+ prompt,
1739
+ model="co/gpt-4o",
1740
+ temperature=0.3,
1741
+ system_prompt="You reflect on tool execution results to generate insights."
1742
+ )
1743
+
1744
+ # Add reflection as assistant message
1745
+ agent.current_session['messages'].append({
1746
+ 'role': 'assistant',
1747
+ 'content': f"💭 {reflection_text}"
1748
+ })
1749
+
1750
+ agent.console.print(f"[dim]💭 {reflection_text}[/dim]")
1751
+ ```
1752
+
1753
+ **Key insights:**
1754
+ - Access agent state via `agent.current_session`
1755
+ - Use `llm_do()` for AI-powered analysis
1756
+ - Add results back to conversation messages
1757
+ - Print to console for user feedback
1758
+
1759
+ **Step 3: Create Plugin (Event List)**
1760
+
1761
+ ```python
1762
+ # Plugin is an event list
1763
+ reflection = [after_tools(_add_reflection)] # after_tools for message injection
1764
+ ```
1765
+
1766
+ **That's it!** A plugin is just an event list.
1767
+
1768
+ **Step 4: Use Your Plugin**
1769
+
1770
+ ```python
1771
+ agent = Agent("assistant", tools=[search], plugins=[reflection])
1772
+ ```
1773
+
1774
+ ### Quick Custom Plugin Example
1775
+
1776
+ Build a simple plugin in 3 lines:
1777
+
1778
+ ```python
1779
+ from connectonion import Agent, after_tool
1780
+
1781
+ def log_tool(agent):
1782
+ trace = agent.current_session['trace'][-1]
1783
+ print(f"✓ {trace['tool_name']} completed in {trace['timing']}ms")
1784
+
1785
+ # Plugin is an event list
1786
+ logger = [after_each_tool(log_tool)] # after_each_tool for per-tool logging
1787
+
1788
+ # Use it
1789
+ agent = Agent("assistant", tools=[search], plugins=[logger])
1790
+ ```
1791
+
1792
+ ### Reusing Plugins
1793
+
1794
+ Use the same plugin across multiple agents:
1795
+
1796
+ ```python
1797
+ # Define once
1798
+ reflection = [after_tools(add_reflection)] # after_tools for message injection
1799
+ logger = [after_llm(log_llm), after_each_tool(log_tool)] # after_each_tool for per-tool logging
1800
+
1801
+ # Use in multiple agents
1802
+ researcher = Agent("researcher", tools=[search], plugins=[reflection, logger])
1803
+ writer = Agent("writer", tools=[generate], plugins=[reflection])
1804
+ analyst = Agent("analyst", tools=[calculate], plugins=[logger])
1805
+ ```
1806
+
1807
+ ### Summary
1808
+
1809
+ **A plugin is an event list:**
1810
+
1811
+ ```python
1812
+ # Define a plugin (an event list)
1813
+ my_plugin = [after_llm(handler1), after_tools(handler2)] # after_tools for message injection
1814
+
1815
+ # Use it (plugins takes a list of event lists)
1816
+ agent = Agent("assistant", tools=[search], plugins=[my_plugin])
1817
+ ```
1818
+
1819
+ **on_events vs plugins:**
1820
+ - `on_events=[after_llm(h1), after_each_tool(h2)]` → one event list
1821
+ - `plugins=[plugin1, plugin2]` → list of event lists
1822
+
1823
+ **Event naming:**
1824
+ - `after_each_tool` → fires for EACH tool (per-tool logging/monitoring)
1825
+ - `after_tools` → fires ONCE after all tools (safe for message injection)
1826
+
1827
+ ---
1828
+
1829
+ ## Best Practices
1830
+
1831
+ ### Principles: Avoid over‑engineering with agents
1832
+
1833
+ - **Delegate interpretation to the agent**: Don't hard‑code parsing rules or use regex to extract parameters; let the agent interpret requests and decide tool arguments.
1834
+ - **Natural language output, not regex parsing**: Let the agent format its own responses naturally. Don't use regex to parse agent output - simply pass through the agent's natural language response. The AI knows how to communicate effectively with users.
1835
+ - **Prompt‑driven clarification**: Put concise follow‑up behavior in the system prompt so the agent asks for missing details (URL, viewport, full‑page, save path) before acting.
1836
+ - **Thin integration layer**: Keep wrappers like `execute_*` minimal—construct the agent, call `agent.input(...)`, and return the natural language response directly.
1837
+ - **No heuristic fallbacks**: If AI is unavailable (e.g., missing API key), return a clear error instead of attempting clever fallback logic.
1838
+ - **Fail fast and clearly**: Only catch exceptions when you can improve user feedback; otherwise surface the error with a short, actionable message.
1839
+ - **Sane defaults, minimal knobs**: Tools should have sensible defaults; the agent overrides them via tool arguments as needed.
1840
+ - **Single source of truth in prompts**: Centralize behavior (clarification rules, parameter choices) in markdown prompts, not scattered in code.
1841
+ - **Test at the seam**: Mock `Agent.input` in tests and validate outcomes; avoid baking tests around internal parsing/branches that shouldn’t exist.
1842
+ - **Extract helpers sparingly**: Factor out helpers only when reused across multiple places; otherwise inline to reduce cognitive load.
1843
+ - **Prefer clarity over cleverness**: Favor descriptive, actionable errors over complex branches trying to “guess” behavior.
1844
+ - **Give the agent interaction budget**: Set `max_iterations` high enough to allow clarification turns rather than coding preemptive guesswork.
1845
+ - **Keep demos separate**: Place advanced flows in examples; keep the core CLI path straightforward and predictable.
1846
+
1847
+ ### Tool Design
1848
+
1849
+ ✅ **Good:**
1850
+ ```python
1851
+ def search_papers(query: str, max_results: int = 10, field: str = "all") -> str:
1852
+ """Search academic papers with specific parameters."""
1853
+ return f"Found {max_results} papers about '{query}' in {field}"
1854
+ ```
1855
+
1856
+ ❌ **Avoid:**
1857
+ ```python
1858
+ def search(q, n=10): # No type hints
1859
+ return "some results" # Vague return
1860
+ ```
1861
+
1862
+ ### Error Handling
1863
+
1864
+ ✅ **Good:**
1865
+ ```python
1866
+ def read_file(filepath: str) -> str:
1867
+ """Read file with proper error handling."""
1868
+ try:
1869
+ with open(filepath, 'r') as f:
1870
+ return f.read()
1871
+ except FileNotFoundError:
1872
+ return f"Error: File '{filepath}' not found"
1873
+ except PermissionError:
1874
+ return f"Error: Permission denied for '{filepath}'"
1875
+ except Exception as e:
1876
+ return f"Error reading file: {e}"
1877
+ ```
1878
+
1879
+ ### Agent Configuration
1880
+
1881
+ ✅ **Good:**
1882
+ ```python
1883
+ # Clear purpose, markdown prompts, appropriate limits
1884
+ data_analyst = Agent(
1885
+ name="data_analyst",
1886
+ system_prompt="prompts/data_scientist.md", # Use markdown files!
1887
+ tools=[load_data, analyze_stats, create_visualization],
1888
+ max_iterations=20 # Data analysis can be multi-step
1889
+ )
1890
+ ```
1891
+
1892
+ ❌ **Avoid:**
1893
+ ```python
1894
+ # Vague purpose, inline prompts, arbitrary limits
1895
+ agent = Agent(
1896
+ name="agent",
1897
+ system_prompt="You are an agent that does stuff. Be helpful and do things when asked. Always be polite and provide good answers...", # Too long inline!
1898
+ tools=[lots_of_random_tools],
1899
+ max_iterations=100 # Way too high
1900
+ )
1901
+ ```
1902
+
1903
+ ### System Prompt Best Practices
1904
+
1905
+ ✅ **Use Markdown Files:**
1906
+ ```python
1907
+ # Recommended approach
1908
+ agent = Agent(
1909
+ name="support_specialist",
1910
+ system_prompt="prompts/customer_support.md",
1911
+ tools=[create_ticket, search_kb]
1912
+ )
1913
+ ```
1914
+
1915
+ ❌ **Avoid Inline Strings:**
1916
+ ```python
1917
+ # Hard to maintain and review
1918
+ agent = Agent(
1919
+ name="support_specialist",
1920
+ system_prompt="You are a customer support specialist. Always be empathetic. Ask clarifying questions. Provide step-by-step solutions. Use professional language...",
1921
+ tools=[create_ticket, search_kb]
1922
+ )
1923
+ ```
1924
+
1925
+ ---
1926
+
1927
+ ## Troubleshooting Guide
1928
+
1929
+ ### Common Issues & Solutions
1930
+
1931
+ **Issue: "Maximum iterations reached"**
1932
+ ```python
1933
+ # Check what happened
1934
+ if "Maximum iterations" in result:
1935
+ # Look at the last record to see what went wrong
1936
+ last_record = agent.history.records[-1]
1937
+ for tool_call in last_record.tool_calls:
1938
+ if tool_call['status'] == 'error':
1939
+ print(f"Tool {tool_call['name']} failed: {tool_call['result']}")
1940
+
1941
+ # Solutions:
1942
+ # 1. Increase iterations
1943
+ result = agent.input(prompt, max_iterations=30)
1944
+
1945
+ # 2. Break down the task
1946
+ step1 = agent.input("First, analyze the data")
1947
+ step2 = agent.input(f"Based on {step1}, create summary")
1948
+ ```
1949
+
1950
+ **Issue: Tools not working**
1951
+ ```python
1952
+ # Check tool registration
1953
+ print(agent.list_tools()) # See what tools are available
1954
+
1955
+ # Check tool schemas
1956
+ for tool in agent.tools:
1957
+ print(tool.to_function_schema())
1958
+ ```
1959
+
1960
+ **Issue: Unexpected behavior**
1961
+ ```python
1962
+ # Use @xray for debugging
1963
+ @xray
1964
+ def debug_tool(input: str) -> str:
1965
+ context = get_xray_context()
1966
+ print(f"Iteration: {context.iteration}")
1967
+ print(f"Previous tools: {context.previous_tools}")
1968
+ return f"Processed: {input}"
1969
+ ```
1970
+
1971
+ ---
1972
+
1973
+ ## When to Use ConnectOnion
1974
+
1975
+ ### Good Use Cases
1976
+ - Building custom AI assistants with specific tools
1977
+ - Automating workflows that need multiple steps
1978
+ - Creating domain-specific chatbots (customer support, data analysis, etc.)
1979
+ - Prototyping agent behaviors with automatic tracking
1980
+ - Educational projects to understand agent architectures
1981
+
1982
+ ### Not Ideal For
1983
+ - Simple single-function calls (just call the function directly)
1984
+ - Real-time applications requiring <100ms response times
1985
+ - Production systems without proper error handling and security
1986
+ - Tasks that don't benefit from LLM reasoning
1987
+
1988
+ ---
1989
+
1990
+ ## Links & Resources
1991
+
1992
+ - **GitHub**: https://github.com/openonion/connectonion
1993
+ - **PyPI**: https://pypi.org/project/connectonion/
1994
+ - **Latest Version**: 0.0.4
1995
+
1996
+ ---
1997
+
1998
+ ## AI Assistant Instructions
1999
+
2000
+ When helping users with ConnectOnion:
2001
+
2002
+ 1. **Start Simple**: Use the basic patterns first, add complexity only when needed
2003
+ 2. **Type Hints**: Always include proper type hints in tool functions
2004
+ 3. **Error Handling**: Add try/catch blocks for robust tools
2005
+ 4. **Iteration Limits**: Help users choose appropriate max_iterations based on task complexity
2006
+ 5. **Debugging**: Suggest @xray decorator when users have issues
2007
+ 6. **Best Practices**: Guide users toward function-based tools over complex classes
2008
+ 7. **Class Instance Tools**: Always recommend passing class instances directly rather than individual methods
2009
+
2010
+ ## Class Instance vs Individual Methods - Key Teaching Point
2011
+
2012
+ **✅ ALWAYS RECOMMEND THIS (Clean & Automatic):**
2013
+ ```python
2014
+ browser = BrowserAutomation()
2015
+ agent = Agent("browser_agent", tools=[browser]) # Auto-discovers all methods!
2016
+ ```
2017
+
2018
+ **❌ AVOID RECOMMENDING THIS (Verbose & Error-prone):**
2019
+ ```python
2020
+ browser = BrowserAutomation()
2021
+ agent = Agent("browser_agent", tools=[
2022
+ browser.start_browser,
2023
+ browser.navigate,
2024
+ browser.take_screenshot,
2025
+ # ... listing every method manually
2026
+ ])
2027
+ ```
2028
+
2029
+ **Why Class Instances Are Better:**
2030
+ - Much cleaner code - one line instead of many
2031
+ - Automatic method discovery - no manual listing required
2032
+ - Less maintenance - add methods to class, they're auto-available
2033
+ - No forgotten methods - everything gets included automatically
2034
+ - This is how ConnectOnion was designed to be used
2035
+
2036
+ Remember: ConnectOnion is designed to make simple things simple and hard things possible. Start with the basics and build up complexity gradually.