10xgraph-api 0.7.0__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 (203) hide show
  1. 10xgraph_api-0.7.0.dist-info/METADATA +618 -0
  2. 10xgraph_api-0.7.0.dist-info/RECORD +203 -0
  3. 10xgraph_api-0.7.0.dist-info/WHEEL +5 -0
  4. 10xgraph_api-0.7.0.dist-info/entry_points.txt +3 -0
  5. 10xgraph_api-0.7.0.dist-info/licenses/LICENSE +21 -0
  6. 10xgraph_api-0.7.0.dist-info/top_level.txt +2 -0
  7. agentflow_cli/__init__.py +69 -0
  8. tenxgraph_api/__init__.py +23 -0
  9. tenxgraph_api/cli/__init__.py +6 -0
  10. tenxgraph_api/cli/capabilities.py +127 -0
  11. tenxgraph_api/cli/commands/__init__.py +49 -0
  12. tenxgraph_api/cli/commands/api.py +262 -0
  13. tenxgraph_api/cli/commands/audit.py +213 -0
  14. tenxgraph_api/cli/commands/build.py +305 -0
  15. tenxgraph_api/cli/commands/config.py +71 -0
  16. tenxgraph_api/cli/commands/demo.py +93 -0
  17. tenxgraph_api/cli/commands/eval.py +909 -0
  18. tenxgraph_api/cli/commands/init.py +531 -0
  19. tenxgraph_api/cli/commands/skills.py +532 -0
  20. tenxgraph_api/cli/commands/test.py +113 -0
  21. tenxgraph_api/cli/commands/version.py +47 -0
  22. tenxgraph_api/cli/config_editor/__init__.py +15 -0
  23. tenxgraph_api/cli/config_editor/schema.py +566 -0
  24. tenxgraph_api/cli/config_editor/server.py +240 -0
  25. tenxgraph_api/cli/config_editor/static/app.css +2 -0
  26. tenxgraph_api/cli/config_editor/static/app.js +3 -0
  27. tenxgraph_api/cli/config_editor/static/favicon.svg +11 -0
  28. tenxgraph_api/cli/config_editor/static/index.html +20 -0
  29. tenxgraph_api/cli/config_editor/store.py +120 -0
  30. tenxgraph_api/cli/config_editor/validation.py +377 -0
  31. tenxgraph_api/cli/constants.py +112 -0
  32. tenxgraph_api/cli/context.py +46 -0
  33. tenxgraph_api/cli/core/__init__.py +0 -0
  34. tenxgraph_api/cli/core/animations.py +550 -0
  35. tenxgraph_api/cli/core/config.py +279 -0
  36. tenxgraph_api/cli/core/output.py +625 -0
  37. tenxgraph_api/cli/core/prompts.py +220 -0
  38. tenxgraph_api/cli/core/screen.py +287 -0
  39. tenxgraph_api/cli/core/steps.py +621 -0
  40. tenxgraph_api/cli/core/theme.py +242 -0
  41. tenxgraph_api/cli/core/validation.py +251 -0
  42. tenxgraph_api/cli/exceptions.py +129 -0
  43. tenxgraph_api/cli/logger.py +84 -0
  44. tenxgraph_api/cli/main.py +936 -0
  45. tenxgraph_api/cli/templates/__init__.py +0 -0
  46. tenxgraph_api/cli/templates/defaults.py +844 -0
  47. tenxgraph_api/cli/templates/dev/.env.example +1 -0
  48. tenxgraph_api/cli/templates/dev/10xgraph.json +16 -0
  49. tenxgraph_api/cli/templates/dev/graph/__init__.py +0 -0
  50. tenxgraph_api/cli/templates/dev/graph/agent.py +63 -0
  51. tenxgraph_api/cli/templates/prod/.env.example +75 -0
  52. tenxgraph_api/cli/templates/prod/.pre-commit-config.yaml +50 -0
  53. tenxgraph_api/cli/templates/prod/.python-version +1 -0
  54. tenxgraph_api/cli/templates/prod/10xgraph.json +42 -0
  55. tenxgraph_api/cli/templates/prod/auth/__init__.py +0 -0
  56. tenxgraph_api/cli/templates/prod/auth/agent_auth.py +46 -0
  57. tenxgraph_api/cli/templates/prod/evals/__init__.py +0 -0
  58. tenxgraph_api/cli/templates/prod/evals/user_simulator_eval.py +76 -0
  59. tenxgraph_api/cli/templates/prod/evals/weather_agents_eval.py +53 -0
  60. tenxgraph_api/cli/templates/prod/graph/__init__.py +0 -0
  61. tenxgraph_api/cli/templates/prod/graph/agent.py +50 -0
  62. tenxgraph_api/cli/templates/prod/graph/state.py +5 -0
  63. tenxgraph_api/cli/templates/prod/graph/thread_name_generator.py +7 -0
  64. tenxgraph_api/cli/templates/prod/graph/tools/__init__.py +0 -0
  65. tenxgraph_api/cli/templates/prod/graph/tools/weather_tool.py +43 -0
  66. tenxgraph_api/cli/templates/prod/graph/validators/__init__.py +0 -0
  67. tenxgraph_api/cli/templates/prod/graph/validators/lifecyle.py +107 -0
  68. tenxgraph_api/cli/templates/prod/graph/validators/manager.py +9 -0
  69. tenxgraph_api/cli/templates/prod/graph/validators/validators.py +21 -0
  70. tenxgraph_api/cli/templates/prod/pyproject.toml +79 -0
  71. tenxgraph_api/cli/templates/prod/tests/__init__.py +0 -0
  72. tenxgraph_api/cli/templates/prod/tests/conftest.py +6 -0
  73. tenxgraph_api/cli/templates/prod/tests/test_agent_eval.py +78 -0
  74. tenxgraph_api/cli/templates/prod/tests/test_catalog_tools.py +47 -0
  75. tenxgraph_api/cli/templates/prod/tests/test_graph_nodes.py +57 -0
  76. tenxgraph_api/cli/templates/skills/10xgraph/SKILL.md +92 -0
  77. tenxgraph_api/cli/templates/skills/10xgraph/references/agents-and-tools.md +389 -0
  78. tenxgraph_api/cli/templates/skills/10xgraph/references/api-client.md +61 -0
  79. tenxgraph_api/cli/templates/skills/10xgraph/references/api-configuration.md +75 -0
  80. tenxgraph_api/cli/templates/skills/10xgraph/references/api-settings-and-middleware.md +89 -0
  81. tenxgraph_api/cli/templates/skills/10xgraph/references/architecture.md +91 -0
  82. tenxgraph_api/cli/templates/skills/10xgraph/references/auth-and-authorization.md +149 -0
  83. tenxgraph_api/cli/templates/skills/10xgraph/references/callbacks-and-command.md +283 -0
  84. tenxgraph_api/cli/templates/skills/10xgraph/references/checkpointing-and-threads.md +63 -0
  85. tenxgraph_api/cli/templates/skills/10xgraph/references/cli-commands.md +73 -0
  86. tenxgraph_api/cli/templates/skills/10xgraph/references/client-auth-and-errors.md +94 -0
  87. tenxgraph_api/cli/templates/skills/10xgraph/references/client-messages-invoke-stream.md +115 -0
  88. tenxgraph_api/cli/templates/skills/10xgraph/references/client-threads-memory-files.md +80 -0
  89. tenxgraph_api/cli/templates/skills/10xgraph/references/context-id-background.md +80 -0
  90. tenxgraph_api/cli/templates/skills/10xgraph/references/dependency-injection.md +58 -0
  91. tenxgraph_api/cli/templates/skills/10xgraph/references/evaluation.md +500 -0
  92. tenxgraph_api/cli/templates/skills/10xgraph/references/id-and-thread-name-generators.md +69 -0
  93. tenxgraph_api/cli/templates/skills/10xgraph/references/media-and-files.md +66 -0
  94. tenxgraph_api/cli/templates/skills/10xgraph/references/memory-and-store.md +70 -0
  95. tenxgraph_api/cli/templates/skills/10xgraph/references/prebuilt-agents-and-tools.md +394 -0
  96. tenxgraph_api/cli/templates/skills/10xgraph/references/production-runtime.md +56 -0
  97. tenxgraph_api/cli/templates/skills/10xgraph/references/providers-and-adapters.md +89 -0
  98. tenxgraph_api/cli/templates/skills/10xgraph/references/publishers-and-runtime-protocols.md +84 -0
  99. tenxgraph_api/cli/templates/skills/10xgraph/references/rate-limiting.md +194 -0
  100. tenxgraph_api/cli/templates/skills/10xgraph/references/realtime.md +172 -0
  101. tenxgraph_api/cli/templates/skills/10xgraph/references/remote-tools.md +55 -0
  102. tenxgraph_api/cli/templates/skills/10xgraph/references/rest-api-and-errors.md +97 -0
  103. tenxgraph_api/cli/templates/skills/10xgraph/references/security-and-validators.md +86 -0
  104. tenxgraph_api/cli/templates/skills/10xgraph/references/state-and-messages.md +68 -0
  105. tenxgraph_api/cli/templates/skills/10xgraph/references/state-graph.md +232 -0
  106. tenxgraph_api/cli/templates/skills/10xgraph/references/stream-emitter.md +144 -0
  107. tenxgraph_api/cli/templates/skills/10xgraph/references/streaming.md +53 -0
  108. tenxgraph_api/cli/templates/skills/10xgraph/references/testing-and-evaluation.md +64 -0
  109. tenxgraph_api/cli/templates/skills/10xgraph/references/unit-testing.md +202 -0
  110. tenxgraph_api/cli/templates/skills/copilot/10xgraph.instructions.md +108 -0
  111. tenxgraph_api/py.typed +0 -0
  112. tenxgraph_api/src/__init__.py +0 -0
  113. tenxgraph_api/src/app/__init__.py +13 -0
  114. tenxgraph_api/src/app/core/__init__.py +15 -0
  115. tenxgraph_api/src/app/core/auth/__init__.py +0 -0
  116. tenxgraph_api/src/app/core/auth/auth_backend.py +38 -0
  117. tenxgraph_api/src/app/core/auth/authorization.py +379 -0
  118. tenxgraph_api/src/app/core/auth/base_auth.py +27 -0
  119. tenxgraph_api/src/app/core/auth/jwt_auth.py +122 -0
  120. tenxgraph_api/src/app/core/auth/ownership_resolver.py +170 -0
  121. tenxgraph_api/src/app/core/auth/permissions.py +354 -0
  122. tenxgraph_api/src/app/core/auth/request_config.py +130 -0
  123. tenxgraph_api/src/app/core/auth/route_guard.py +105 -0
  124. tenxgraph_api/src/app/core/config/__init__.py +0 -0
  125. tenxgraph_api/src/app/core/config/graph_config.py +532 -0
  126. tenxgraph_api/src/app/core/config/media_settings.py +72 -0
  127. tenxgraph_api/src/app/core/config/sentry_config.py +60 -0
  128. tenxgraph_api/src/app/core/config/settings.py +202 -0
  129. tenxgraph_api/src/app/core/config/setup_logs.py +65 -0
  130. tenxgraph_api/src/app/core/config/setup_middleware.py +483 -0
  131. tenxgraph_api/src/app/core/config/worker_middleware.py +99 -0
  132. tenxgraph_api/src/app/core/exceptions/__init__.py +17 -0
  133. tenxgraph_api/src/app/core/exceptions/general_exception.py +58 -0
  134. tenxgraph_api/src/app/core/exceptions/handle_errors.py +363 -0
  135. tenxgraph_api/src/app/core/exceptions/resources_exceptions.py +72 -0
  136. tenxgraph_api/src/app/core/exceptions/user_exception.py +58 -0
  137. tenxgraph_api/src/app/core/middleware/__init__.py +25 -0
  138. tenxgraph_api/src/app/core/middleware/rate_limit/__init__.py +15 -0
  139. tenxgraph_api/src/app/core/middleware/rate_limit/base.py +27 -0
  140. tenxgraph_api/src/app/core/middleware/rate_limit/factory.py +98 -0
  141. tenxgraph_api/src/app/core/middleware/rate_limit/keying.py +133 -0
  142. tenxgraph_api/src/app/core/middleware/rate_limit/memory.py +98 -0
  143. tenxgraph_api/src/app/core/middleware/rate_limit/middleware.py +90 -0
  144. tenxgraph_api/src/app/core/middleware/rate_limit/redis.py +115 -0
  145. tenxgraph_api/src/app/core/middleware/request_limits.py +154 -0
  146. tenxgraph_api/src/app/core/middleware/security_headers.py +239 -0
  147. tenxgraph_api/src/app/core/utils/__init__.py +14 -0
  148. tenxgraph_api/src/app/core/utils/log_sanitizer.py +216 -0
  149. tenxgraph_api/src/app/loader.py +516 -0
  150. tenxgraph_api/src/app/main.py +180 -0
  151. tenxgraph_api/src/app/routers/__init__.py +4 -0
  152. tenxgraph_api/src/app/routers/ag_ui/__init__.py +10 -0
  153. tenxgraph_api/src/app/routers/ag_ui/converter.py +195 -0
  154. tenxgraph_api/src/app/routers/ag_ui/event_mapper.py +353 -0
  155. tenxgraph_api/src/app/routers/ag_ui/router.py +90 -0
  156. tenxgraph_api/src/app/routers/ag_ui/service.py +193 -0
  157. tenxgraph_api/src/app/routers/checkpointer/__init__.py +1 -0
  158. tenxgraph_api/src/app/routers/checkpointer/router.py +482 -0
  159. tenxgraph_api/src/app/routers/checkpointer/schemas/__init__.py +1 -0
  160. tenxgraph_api/src/app/routers/checkpointer/schemas/checkpointer_schemas.py +121 -0
  161. tenxgraph_api/src/app/routers/checkpointer/services/__init__.py +1 -0
  162. tenxgraph_api/src/app/routers/checkpointer/services/checkpointer_service.py +300 -0
  163. tenxgraph_api/src/app/routers/evals/__init__.py +6 -0
  164. tenxgraph_api/src/app/routers/evals/router.py +38 -0
  165. tenxgraph_api/src/app/routers/evals/services/__init__.py +1 -0
  166. tenxgraph_api/src/app/routers/evals/services/eval_report_service.py +354 -0
  167. tenxgraph_api/src/app/routers/graph/__init__.py +6 -0
  168. tenxgraph_api/src/app/routers/graph/realtime_guard.py +161 -0
  169. tenxgraph_api/src/app/routers/graph/router.py +821 -0
  170. tenxgraph_api/src/app/routers/graph/schemas/__init__.py +1 -0
  171. tenxgraph_api/src/app/routers/graph/schemas/graph_schemas.py +386 -0
  172. tenxgraph_api/src/app/routers/graph/services/__init__.py +1 -0
  173. tenxgraph_api/src/app/routers/graph/services/graph_service.py +1219 -0
  174. tenxgraph_api/src/app/routers/graph/services/multimodal_preprocessor.py +164 -0
  175. tenxgraph_api/src/app/routers/media/__init__.py +506 -0
  176. tenxgraph_api/src/app/routers/media/router.py +242 -0
  177. tenxgraph_api/src/app/routers/media/schemas.py +39 -0
  178. tenxgraph_api/src/app/routers/ping/__init__.py +4 -0
  179. tenxgraph_api/src/app/routers/ping/router.py +28 -0
  180. tenxgraph_api/src/app/routers/setup_router.py +60 -0
  181. tenxgraph_api/src/app/routers/store/__init__.py +4 -0
  182. tenxgraph_api/src/app/routers/store/router.py +200 -0
  183. tenxgraph_api/src/app/routers/store/schemas/__init__.py +28 -0
  184. tenxgraph_api/src/app/routers/store/schemas/store_schemas.py +200 -0
  185. tenxgraph_api/src/app/routers/store/services/__init__.py +4 -0
  186. tenxgraph_api/src/app/routers/store/services/store_service.py +203 -0
  187. tenxgraph_api/src/app/tasks/__init__.py +0 -0
  188. tenxgraph_api/src/app/tasks/user_tasks.py +38 -0
  189. tenxgraph_api/src/app/utils/__init__.py +12 -0
  190. tenxgraph_api/src/app/utils/callable_helper.py +26 -0
  191. tenxgraph_api/src/app/utils/media/__init__.py +15 -0
  192. tenxgraph_api/src/app/utils/media/extractor.py +172 -0
  193. tenxgraph_api/src/app/utils/media/pipeline.py +83 -0
  194. tenxgraph_api/src/app/utils/parse_output.py +17 -0
  195. tenxgraph_api/src/app/utils/response_helper.py +129 -0
  196. tenxgraph_api/src/app/utils/schemas/__init__.py +11 -0
  197. tenxgraph_api/src/app/utils/schemas/output_schemas.py +28 -0
  198. tenxgraph_api/src/app/utils/schemas/user_schemas.py +13 -0
  199. tenxgraph_api/src/app/utils/snowflake_id_generator.py +90 -0
  200. tenxgraph_api/src/app/utils/swagger_helper.py +160 -0
  201. tenxgraph_api/src/app/utils/telemetry_store.py +123 -0
  202. tenxgraph_api/src/app/utils/thread_name_generator.py +304 -0
  203. tenxgraph_api/src/app/worker.py +91 -0
@@ -0,0 +1,91 @@
1
+ # Architecture
2
+
3
+ Use this when deciding where a change belongs or explaining how 10xGraph packages interact. Check https://10xgraph.com/ first for public package names.
4
+
5
+ ---
6
+
7
+ ## Published packages
8
+
9
+ | Public package | Registry | Install | Source |
10
+ |---|---|---|---|
11
+ | `10xgraph` | PyPI | `pip install 10xgraph` | `tenxgraph/` in 10xGraph/10xGraph |
12
+ | `10xgraph-api` | PyPI | `pip install 10xgraph-api` | `10xgraph-api/tenxgraph_api` |
13
+ | `@10xscale/agentflow-client` | npm | `npm install @10xscale/agentflow-client` | `agentflow-client/src` |
14
+
15
+ ---
16
+
17
+ ## Layer responsibilities
18
+
19
+ ### `10xgraph` — core Python library
20
+
21
+ | Sub-package | Key exports |
22
+ |---|---|
23
+ | `tenxgraph.core` | `StateGraph`, `Agent`, `ToolNode`, `AgentState`, `Message`, `StreamChunk` |
24
+ | `tenxgraph.prebuilt.agent` | `ReactAgent`, `PlanActReflectAgent`, `StructuredOutputAgent`, `SupervisorTeamAgent`, `SwarmAgent`, `RAGAgent`, `AudioAgent` (realtime voice) |
25
+ | `tenxgraph.core.realtime` | `LiveInputQueue`, `RealtimeConfig`, `RealtimeEvent` (Gemini Live audio-to-audio) |
26
+ | `tenxgraph.prebuilt.tools` | `fetch_url`, `safe_calculator`, `file_read`, `file_write`, `file_search`, `google_web_search`, `vertex_ai_search`, `memory_tool`, `create_handoff_tool` |
27
+ | `tenxgraph.storage.checkpointer` | `InMemoryCheckpointer`, `PgCheckpointer` |
28
+ | `tenxgraph.storage.store` | `QdrantStore`, `Mem0Store` |
29
+ | `tenxgraph.storage.media` | `InMemoryMediaStore`, `LocalFileMediaStore`, `CloudMediaStore` |
30
+ | `tenxgraph.runtime` | Publisher adapters (SSE, A2A, Kafka, RabbitMQ, Redis Pub/Sub) |
31
+ | `tenxgraph.utils` | `ResponseGranularity`, `CallbackManager`, `tool` decorator |
32
+ | `tenxgraph.qa` | Testing helpers and evaluation tools |
33
+
34
+ ### `10xgraph-api` — API and CLI
35
+
36
+ Owns `10xgraph api`, `10xgraph play`, `10xgraph init`, `10xgraph build`, REST routers, auth/middleware, config loading, and graph service execution.
37
+
38
+ ### `@10xscale/agentflow-client` — TypeScript HTTP client
39
+
40
+ Typed methods for invoke, stream, threads, memory store, file uploads, graph metadata, remote tools, and auth helpers. Calls a running 10xGraph API server — does not run Python graphs.
41
+
42
+ ---
43
+
44
+ ## Request flow: invoke
45
+
46
+ 1. `@10xscale/agentflow-client` or another HTTP caller sends messages plus `config.thread_id`.
47
+ 2. FastAPI receives the request through auth and routers.
48
+ 3. `GraphService` invokes against the compiled graph loaded at startup.
49
+ 4. The compiled graph loads state from the checkpointer when `thread_id` exists.
50
+ 5. Graph nodes run and update `AgentState`.
51
+ 6. Checkpointer saves state, messages, and thread metadata.
52
+ 7. API returns JSON to the caller.
53
+
54
+ ## Request flow: stream
55
+
56
+ Identical through authentication and state loading. The difference: the graph sends `StreamChunk` events incrementally via SSE. Each chunk carries `event` (`"message"`, `"state"`, `"error"`, or `"updates"`), and the response is a `StreamingResponse`.
57
+
58
+ ---
59
+
60
+ ## Key design decisions
61
+
62
+ | Decision | Rationale |
63
+ |---|---|
64
+ | Graph compiled once at startup | Avoids repeated module loading per request |
65
+ | `thread_id` in every request | Allows stateless servers to restore conversation history |
66
+ | Checkpointer is injected, not hardcoded | Graph code does not depend on the storage backend |
67
+ | Auth is middleware, not in the graph | Business logic stays separate from access control |
68
+ | `injectq` for service wiring | Nodes and tools declare dependencies declaratively; the runtime resolves them |
69
+
70
+ ---
71
+
72
+ ## Design rules
73
+
74
+ - Compile graphs once at startup for API serving.
75
+ - Keep graph code storage-agnostic; wire checkpointer/store/media/dependencies through compile arguments, `InjectQ`, or `10xgraph.json`.
76
+ - Treat `thread_id` as the continuity key for conversation state.
77
+ - Treat long-term memory store records as cross-thread knowledge, not thread history.
78
+ - Keep auth and request permissions in API middleware/routers, not inside graph nodes.
79
+
80
+ ---
81
+
82
+ ## Source map
83
+
84
+ - Core graph: https://github.com/10xGraph/10xGraph/tree/main/tenxgraph/core/graph
85
+ - State/message models: https://github.com/10xGraph/10xGraph/tree/main/tenxgraph/core/state
86
+ - Checkpointers: https://github.com/10xGraph/10xGraph/tree/main/tenxgraph/storage/checkpointer
87
+ - Memory stores: https://github.com/10xGraph/10xGraph/tree/main/tenxgraph/storage/store
88
+ - Media stores: https://github.com/10xGraph/10xGraph/tree/main/tenxgraph/storage/media
89
+ - API routers: https://github.com/10xGraph/10xgraph-api/tree/main/tenxgraph_api/src/app/routers
90
+ - TS client: https://github.com/10xHub/agentflow-client/blob/main/src/client.ts
91
+ - Concepts: https://10xgraph.com/concepts/architecture
@@ -0,0 +1,149 @@
1
+ # Auth and Authorization
2
+
3
+ Use this when changing HTTP authentication, authorization, permission checks, scopes, storage
4
+ isolation, or client auth examples.
5
+
6
+ Two independent layers:
7
+
8
+ - Authentication (`BaseAuth`): who is the caller? Produces a `user` dict.
9
+ - Authorization (`AuthorizationBackend`): what may they do, and whose data can they touch?
10
+
11
+ ## Authentication Modes
12
+
13
+ Default:
14
+
15
+ - `auth: null`
16
+ - No authentication. Local development / trusted gateways only.
17
+
18
+ JWT:
19
+
20
+ - `auth: "jwt"`
21
+ - Requires `JWT_SECRET_KEY` and `JWT_ALGORITHM`. Token must carry `user_id` and `exp`.
22
+ - Requests use `Authorization: Bearer <token>`. Decoded payload becomes the `user` context.
23
+
24
+ Custom:
25
+
26
+ ```json
27
+ { "auth": { "method": "custom", "path": "graph.auth:MyAuthBackend" } }
28
+ ```
29
+
30
+ Custom backends subclass `BaseAuth`. `authenticate` is **synchronous** (called without `await`)
31
+ and takes three args:
32
+
33
+ ```python
34
+ def authenticate(self, request, response, credential) -> dict | None: ...
35
+ ```
36
+
37
+ - `request` may be a `Request` or a `WebSocket` (both are `HTTPConnection`) — read
38
+ `request.headers`, do not assume Request-only APIs.
39
+ - `credential` is the parsed bearer token (`HTTPAuthorizationCredentials | None`). For
40
+ API-key/cookie schemes, ignore it and read headers directly.
41
+ - Return a dict with at least `user_id` (keys flow into `config["user"]`); `{}`/`None` = anonymous;
42
+ raise `UserAccountError`/`HTTPException` to reject (401 HTTP, 1008 close on WebSocket).
43
+ - Do NOT declare it `async def` — an un-awaited coroutine breaks auth silently.
44
+ - Include `roles` / `scopes` in the returned dict to feed authorization.
45
+
46
+ ## Authorization
47
+
48
+ Configured via the `authorization` key; separate from `auth`. Values:
49
+
50
+ - `null` (unset): mode-based default — `"ownership"` in production, `"allow_all"` in development.
51
+ - `"ownership"`: owner-only. A thread is readable/runnable/deletable only by its creator; a
52
+ foreign `invoke`/`stream` is rejected up front (403). Enforced on every thread-touching step.
53
+ - `"allow_all"` (aliases `"default"`, `"none"`): any authenticated user may do anything.
54
+ - `"module:attr"`: custom `AuthorizationBackend`.
55
+ - `{ "backend": "rbac", ... }`: role-based access control (below).
56
+
57
+ Ownership is scalable: ownership is immutable, so it is cached (in-process LRU + optional shared
58
+ Redis when `redis`/`REDIS_URL` is set) via `ThreadOwnershipResolver` over
59
+ `BaseCheckpointer.aget_thread_owner`. After the first lookup a check is an in-memory hit, not a
60
+ per-request DB call; the cache is evicted on thread deletion. Ownership needs a persistent
61
+ checkpointer (pg/sqlite/in-memory); with none, requests pass through.
62
+
63
+ ### Custom backend interface
64
+
65
+ ```python
66
+ class MyAuthz(AuthorizationBackend):
67
+ async def authorize(
68
+ self, user: dict, resource: str, action: str,
69
+ resource_id: str | None = None, **context,
70
+ ) -> bool: ... # required; False -> 403
71
+
72
+ def isolation_scope(self) -> str: # optional; "owner" | "none" (default "none")
73
+ return "owner"
74
+
75
+ def scopes_for(self, user: dict) -> list[str] | None: # optional; None = permissive
76
+ return user.get("scopes")
77
+ ```
78
+
79
+ Subclass `OwnershipAuthorizationBackend` to inherit cached owner-only checks and override only
80
+ what you need.
81
+
82
+ ### Scopes
83
+
84
+ Each endpoint requires the scope `"<resource>:<action>"`. `RequirePermission` checks it against
85
+ `authz.scopes_for(user)`; `None` = permissive (default, nothing breaks until scopes are issued).
86
+
87
+ - `graph`: `invoke`, `stream`, `stop`, `fix`, `setup`, `read`
88
+ - `checkpointer`: `read`, `write`, `delete`
89
+ - `store`: `read`, `write`, `delete`
90
+ - `files`: `upload`, `read`
91
+ - `config`: `read`
92
+
93
+ ### RBAC config (no code)
94
+
95
+ ```json
96
+ {
97
+ "authorization": {
98
+ "backend": "rbac",
99
+ "roles": { "admin": ["*"], "member": ["graph:invoke", "checkpointer:read"] },
100
+ "default_scopes": ["graph:read"],
101
+ "isolation": "owner"
102
+ }
103
+ }
104
+ ```
105
+
106
+ Maps `user["roles"]` to scopes on top of owner isolation. `"*"` -> all scopes. `default_scopes`
107
+ granted to everyone. `isolation`: `"owner"` | `"none"`.
108
+
109
+ ### Data isolation (config["authz"])
110
+
111
+ API checks decide access; the storage layer (checkpointer, store) enforces isolation from a
112
+ trusted policy. After a successful check, `RequirePermission` stamps
113
+ `user["authz"] = {user_id, scope, scopes}` where `scope` = backend `isolation_scope()`. Services
114
+ copy the trusted `user` into `config["user"]`, so the core library reads `config["user"]["authz"]`
115
+ and scopes rows to the caller (`owner`) or not (`none`). Set server-side only — not client-forgeable.
116
+
117
+ ## Guarantees
118
+
119
+ - Routes are guarded by construction: `assert_all_routes_protected` refuses to boot if any
120
+ non-public route lacks `RequirePermission`. Public: `/ping` and dev-only eval endpoints.
121
+ - Return 401 for auth failure, 403 for authorization/scope failure.
122
+
123
+ ## TypeScript Client
124
+
125
+ ```typescript
126
+ const client = new AgentFlowClient({
127
+ baseUrl: "http://127.0.0.1:8000",
128
+ headers: { Authorization: `Bearer ${token}` },
129
+ });
130
+ ```
131
+
132
+ ## Rules
133
+
134
+ - No unauthenticated API mode in production unless a trusted gateway handles auth.
135
+ - Keep `authenticate` synchronous; keep authorization out of graph business logic.
136
+ - Sanitize logging for tokens and user payloads.
137
+ - Update the scope catalog and permission tables when adding routes.
138
+
139
+ ## Source Map
140
+
141
+ - Base auth: tenxgraph_api/src/app/core/auth/base_auth.py
142
+ - JWT auth: tenxgraph_api/src/app/core/auth/jwt_auth.py
143
+ - Auth loader/dependency: tenxgraph_api/src/app/core/auth/auth_backend.py
144
+ - Authorization backends (ownership, RBAC): tenxgraph_api/src/app/core/auth/authorization.py
145
+ - Permission dependency + scope check + authz stamp: tenxgraph_api/src/app/core/auth/permissions.py
146
+ - Ownership cache: tenxgraph_api/src/app/core/auth/ownership_resolver.py
147
+ - Boot-time route guard: tenxgraph_api/src/app/core/auth/route_guard.py
148
+ - Scope catalog + authz contract: tenxgraph/core/authz.py
149
+ - Docs: https://10xgraph.com/
@@ -0,0 +1,283 @@
1
+ # Callbacks and Command
2
+
3
+ Use this when adding validation, tracing, invocation hooks, error recovery, or runtime graph jumps.
4
+
5
+ ## CallbackManager
6
+
7
+ `CallbackManager` registers hooks around AI, tool, MCP, input validation, and skill invocations.
8
+
9
+ Invocation types:
10
+
11
+ - `InvocationType.AI`
12
+ - `InvocationType.TOOL`
13
+ - `InvocationType.MCP`
14
+ - `InvocationType.INPUT_VALIDATION`
15
+ - `InvocationType.SKILL`
16
+
17
+ Hook families:
18
+
19
+ - `register_before_invoke(invocation_type, callback)`: validate or transform input before invocation.
20
+ - `register_after_invoke(invocation_type, callback)`: inspect or transform output after invocation.
21
+ - `register_on_error(invocation_type, callback)`: log, recover, or return a recovery `Message`.
22
+ - `register_input_validator(validator)`: add a `BaseValidator` that validates incoming messages.
23
+
24
+ Callbacks can be callable objects or functions and may be sync or async. Error callbacks should return a `Message` recovery value or `None`.
25
+
26
+ ## Validators
27
+
28
+ Use `BaseValidator` for input validation. Implement:
29
+
30
+ ```python
31
+ async def validate(self, messages: list[Message]) -> bool:
32
+ ...
33
+ ```
34
+
35
+ Register validators on a `CallbackManager`, then pass it to graph compilation:
36
+
37
+ ```python
38
+ callback_manager = CallbackManager()
39
+ callback_manager.register_input_validator(MyValidator())
40
+
41
+ app = graph.compile(callback_manager=callback_manager)
42
+ ```
43
+
44
+ Use validators for safety checks, business rules, input policy, and prompt-injection detection.
45
+
46
+ ## Graph Lifecycle Hooks
47
+
48
+ Graph lifecycle hooks fire at **graph orchestration level** — before/after the entire graph run, on checkpoints, on interrupts, on resume, and after each node transition. They complement the invocation-level hooks above (`before_invoke` / `after_invoke` / `on_error`), which fire inside a single node's AI/Tool/MCP call.
49
+
50
+ ### GraphLifecycleContext
51
+
52
+ All 7 hooks receive this as their first argument. It provides run-identifying metadata.
53
+
54
+ ```python
55
+ @dataclass
56
+ class GraphLifecycleContext:
57
+ config: dict[str, Any] # full config dict passed to invoke/stream
58
+ timestamp: str # ISO8601 start time from config["timestamp"]
59
+ metadata: dict[str, Any] | None = None # open-ended extra context
60
+
61
+ @property
62
+ def thread_id(self) -> str | None: ...
63
+
64
+ @property
65
+ def run_id(self) -> str | None: ...
66
+ ```
67
+
68
+ ### GraphLifecycleHook
69
+
70
+ Subclass `GraphLifecycleHook` and override only the methods you need. All methods are async and default to no-ops.
71
+
72
+ ```python
73
+ from tenxgraph.utils.callbacks import GraphLifecycleHook, GraphLifecycleContext, CallbackManager
74
+ from tenxgraph.core.state import AgentState
75
+ from tenxgraph.core.state.message import Message
76
+
77
+ class GraphLifecycleHook(ABC):
78
+ async def on_graph_start(
79
+ self, context: GraphLifecycleContext, state: AgentState
80
+ ) -> AgentState | None: ...
81
+ # Fires: after state is loaded, before the first node executes.
82
+ # Return modified AgentState to replace the initial state, or None.
83
+
84
+ async def on_graph_end(
85
+ self, context: GraphLifecycleContext, final_state: AgentState,
86
+ messages: list[Message], total_steps: int
87
+ ) -> AgentState | None: ...
88
+ # Fires: after execution loop completes, before final persistence.
89
+ # Return modified AgentState or None.
90
+
91
+ async def on_graph_error(
92
+ self, context: GraphLifecycleContext, error: Exception,
93
+ partial_state: AgentState, messages: list[Message], step: int, node_name: str
94
+ ) -> tuple[AgentState, str] | None: ...
95
+ # Fires: when an unhandled exception escapes the graph loop.
96
+ # Return (AgentState, error_message) to change persisted error snapshot, or None.
97
+ # Cannot suppress the error — always re-raised after this hook.
98
+
99
+ async def on_interrupt(
100
+ self, context: GraphLifecycleContext, interrupted_node: str,
101
+ interrupt_type: str, # "before" | "after" | "stop" | "remote_tool"
102
+ state: AgentState
103
+ ) -> AgentState | None: ...
104
+ # Fires: before interrupt state is persisted (covers before/after/stop/remote_tool types).
105
+ # Return modified AgentState or None.
106
+
107
+ async def on_resume(
108
+ self, context: GraphLifecycleContext, resumed_node: str,
109
+ state: AgentState, resume_data: dict[str, Any]
110
+ ) -> AgentState | None: ...
111
+ # Fires: when a paused graph is resumed, before clear_interrupt().
112
+ # resume_data is mutable in-place. Return modified AgentState or None.
113
+
114
+ async def on_checkpoint(
115
+ self, context: GraphLifecycleContext, state: AgentState,
116
+ messages: list[Message], is_context_trimmed: bool
117
+ ) -> tuple[AgentState, list[Message]] | AgentState | None: ...
118
+ # Fires: immediately before state/messages are persisted (every checkpoint, not just final).
119
+ # Return (AgentState, messages), AgentState, or None.
120
+
121
+ async def on_state_update(
122
+ self, context: GraphLifecycleContext, node_name: str,
123
+ old_state: AgentState, new_state: AgentState, step: int
124
+ ) -> AgentState | None: ...
125
+ # Fires: after each node produces a result and state is merged.
126
+ # Return modified AgentState or None.
127
+ ```
128
+
129
+ ### Registration
130
+
131
+ ```python
132
+ callback_mgr = CallbackManager()
133
+ callback_mgr.register_lifecycle_hook(MyHook())
134
+
135
+ # Combine with existing invocation-level hooks on the same manager:
136
+ callback_mgr.register_after_invoke(InvocationType.AI, my_ai_callback)
137
+
138
+ app = graph.compile(callback_manager=callback_mgr)
139
+ ```
140
+
141
+ ### Hook Summary
142
+
143
+ | Hook | Returns | Fires N times | Fire location |
144
+ |---|---|---|---|
145
+ | `on_graph_start` | `AgentState \| None` | 1 per run | After state load, before loop |
146
+ | `on_graph_end` | `AgentState \| None` | 1 per successful run | After `state.complete()`, before final `sync_data()` |
147
+ | `on_graph_error` | `tuple[AgentState, str] \| None` | 1 per failed run | In except block, before error `sync_data()` |
148
+ | `on_interrupt` | `AgentState \| None` | 0–N per run | Before interrupt checkpoint persistence |
149
+ | `on_resume` | `AgentState \| None` | 0–1 per call | Before `clear_interrupt()` |
150
+ | `on_checkpoint` | `(AgentState, list[Message]) \| AgentState \| None` | 1–N per run | Before every durable checkpoint write |
151
+ | `on_state_update` | `AgentState \| None` | N per run (once per node) | After each node result is merged |
152
+ | `on_turn_start` | `AgentState \| None` | N (realtime only) | Start of each model turn |
153
+ | `on_turn_end` | `AgentState \| None` | N (realtime only) | End of each model turn |
154
+
155
+ ### Realtime hooks
156
+
157
+ The same `GraphLifecycleHook` fires for realtime (audio) graphs, with two methods that fire **only**
158
+ in realtime (no-ops for `invoke` / `stream`):
159
+
160
+ - `on_graph_start(ctx, state)` / `on_graph_end(ctx, final_state, messages, total_steps)` — once per
161
+ session (the `LIVE` node *is* the graph); `total_steps` = number of turns.
162
+ - `on_turn_start(ctx, state, turn_index)` / `on_turn_end(ctx, state, turn_index)` — per model turn
163
+ (1-based; a turn spans one model generation, bounded by `turn_complete` or a barge-in). A turn cut
164
+ off by session end still gets a balanced `on_turn_end`.
165
+
166
+ Realtime has no `AI`-invocation callback or input-validator pass (no discrete LLM call); the per-turn
167
+ hooks are the observability stand-in. Tool/MCP `before/after/error` callbacks fire as usual. See
168
+ `realtime.md`.
169
+
170
+ ### Example
171
+
172
+ ```python
173
+ class ObservabilityHook(GraphLifecycleHook):
174
+ async def on_graph_start(self, ctx, state):
175
+ self._span = tracer.start_span(f"graph.run.{ctx.thread_id}")
176
+ return None
177
+
178
+ async def on_graph_end(self, ctx, final_state, messages, total_steps):
179
+ self._span.set_attribute("steps", total_steps)
180
+ self._span.end()
181
+
182
+ async def on_graph_error(self, ctx, error, partial_state, messages, step, node_name):
183
+ self._span.record_exception(error)
184
+ self._span.end()
185
+ alert_oncall(f"Graph failed at node {node_name}: {error}")
186
+ return None
187
+
188
+ async def on_interrupt(self, ctx, interrupted_node, interrupt_type, state):
189
+ notify_frontend(ctx.thread_id, status="waiting_for_input", node=interrupted_node)
190
+ return None
191
+
192
+ async def on_resume(self, ctx, resumed_node, state, resume_data):
193
+ notify_frontend(ctx.thread_id, status="resuming", node=resumed_node)
194
+ return None
195
+
196
+ async def on_checkpoint(self, ctx, state, messages, is_context_trimmed):
197
+ metrics.increment("tenxgraph.checkpoints", tags={"thread": ctx.thread_id})
198
+ return None
199
+
200
+ async def on_state_update(self, ctx, node_name, old_state, new_state, step):
201
+ diff = compute_diff(old_state, new_state)
202
+ stream_diff_to_frontend(ctx.thread_id, diff)
203
+ return None
204
+
205
+
206
+ callback_mgr = CallbackManager()
207
+ callback_mgr.register_lifecycle_hook(ObservabilityHook())
208
+ app = graph.compile(callback_manager=callback_mgr)
209
+ ```
210
+
211
+ ### Common Use Cases by Hook
212
+
213
+ - **`on_graph_start`**: inject trace IDs, pre-populate state from external DB, set rate-limit budgets, initialize OpenTelemetry spans.
214
+ - **`on_graph_end`**: send completion notifications (Slack/email), record step/message count metrics, archive transcripts, trigger downstream webhooks.
215
+ - **`on_graph_error`**: alert PagerDuty/Sentry, log structured failure diagnostics, close OTel spans with error status.
216
+ - **`on_interrupt`**: push "waiting for approval" notifications to frontend/mobile, start timeout timers, update task queue status.
217
+ - **`on_resume`**: cancel timeout timers, validate resume payload, record interrupt→resume cycle for audit trail.
218
+ - **`on_checkpoint`**: redact sensitive data before persistence, replicate to secondary store, invalidate caches, compliance audit logging (SOC2/HIPAA).
219
+ - **`on_state_update`**: real-time state diffing for frontend streaming, per-node invariant assertions, security scanning of state content.
220
+
221
+ ---
222
+
223
+ ## Command
224
+
225
+ `Command` lets a node combine state/message updates with control flow. Use it when the next node depends on runtime logic inside the node and is awkward to express as a static conditional edge.
226
+
227
+ Fields:
228
+
229
+ - `update`: state update, `Message`, string, converter, or `None`.
230
+ - `goto`: next node name or `END`.
231
+ - `graph`: optional graph target; `Command.PARENT` is reserved for parent graph navigation patterns.
232
+ - `state`: optional attached state.
233
+
234
+ Prefer conditional edges for normal routing because they are easier to visualize and test. Use `Command(goto=...)` for dynamic jumps, recovery branches, handoffs, or side-effect-dependent routing.
235
+
236
+ ## Patterns
237
+
238
+ Callback for tracing:
239
+
240
+ ```python
241
+ from tenxgraph.utils.callbacks import CallbackContext, CallbackManager, InvocationType
242
+
243
+ async def trace_after(context: CallbackContext, input_data, output_data):
244
+ print(context.invocation_type, context.node_name)
245
+ return output_data
246
+
247
+ callback_manager = CallbackManager()
248
+ callback_manager.register_after_invoke(InvocationType.TOOL, trace_after)
249
+ app = graph.compile(callback_manager=callback_manager)
250
+ ```
251
+
252
+ Command for dynamic routing:
253
+
254
+ ```python
255
+ from tenxgraph.utils import Command, END
256
+
257
+ def router_node(state, config):
258
+ if state.context[-1].text() == "stop":
259
+ return Command(goto=END)
260
+ return Command(update={"route": "repair"}, goto="REPAIR")
261
+ ```
262
+
263
+ ## Rules
264
+
265
+ - Keep callback side effects bounded; they run inside graph execution paths.
266
+ - Avoid storing per-request mutable state globally inside callbacks.
267
+ - Use `CallbackContext` metadata to distinguish node/function/invocation details.
268
+ - Return transformed data from callbacks only when the downstream invocation expects that shape.
269
+ - Use `Command` sparingly; static and conditional edges remain the default graph structure.
270
+ - Always test command routes for recursion limits and missing destination nodes.
271
+
272
+ ## Source Map
273
+
274
+ - Callback system (invocation hooks + graph lifecycle hooks): https://github.com/10xGraph/10xGraph/blob/main/tenxgraph/utils/callbacks.py
275
+ - Default validators: https://github.com/10xGraph/10xGraph/blob/main/tenxgraph/utils/validators.py
276
+ - Graph compile callback argument: https://github.com/10xGraph/10xGraph/blob/main/tenxgraph/core/graph/state_graph.py
277
+ - Command API: https://github.com/10xGraph/10xGraph/blob/main/tenxgraph/utils/command.py
278
+ - Command execution paths: https://github.com/10xGraph/10xGraph/blob/main/tenxgraph/core/graph/compiled_graph.py
279
+ - Lifecycle hook fire points — invoke path: https://github.com/10xGraph/10xGraph/blob/main/tenxgraph/core/graph/utils/invoke_handler.py
280
+ - Lifecycle hook fire points — stream path: https://github.com/10xGraph/10xGraph/blob/main/tenxgraph/core/graph/utils/stream_handler.py
281
+ - Lifecycle hook fire points — interrupt/resume: https://github.com/10xGraph/10xGraph/blob/main/tenxgraph/core/graph/utils/heandler_utils.py
282
+ - Lifecycle hook fire points — checkpoint: https://github.com/10xGraph/10xGraph/blob/main/tenxgraph/core/graph/utils/utils.py
283
+ - Legacy docs: https://github.com/10xHub/Agentflow/blob/main/agentflow-docs/docs-mkdocs-legacy/reference/library/Command.md
@@ -0,0 +1,63 @@
1
+ # Checkpointing and Threads
2
+
3
+ Use this when adding persistence, thread APIs, message history, interrupts, or multi-worker behavior.
4
+
5
+ ## Concept
6
+
7
+ A checkpointer persists per-thread `AgentState`, messages, and thread metadata. Without a checkpointer, each `invoke` starts from a fresh state. With a checkpointer, calls with the same `config.thread_id` resume the saved state.
8
+
9
+ ## Config
10
+
11
+ At minimum, checkpointed calls need:
12
+
13
+ ```python
14
+ config = {"thread_id": "conv-1"}
15
+ ```
16
+
17
+ Use `user_id` for multi-tenant scoping where the backend supports it.
18
+
19
+ ## Backends
20
+
21
+ - `InMemoryCheckpointer`: development/tests/single-process only. State is lost on restart and not shared across workers.
22
+ - `PgCheckpointer`: production backend using PostgreSQL for durable data and Redis for fast cache. Requires setup before use.
23
+
24
+ Use production storage for load-balanced API deployments.
25
+
26
+ ## API Surface
27
+
28
+ Checkpointer methods exist in async and sync forms:
29
+
30
+ - State: put/get/clear state and state cache.
31
+ - Messages: append/list/get/delete thread messages.
32
+ - Threads: create/get/list/clean thread metadata and content.
33
+ - Generic cache: namespaced key-value cache with optional TTL.
34
+
35
+ ## REST and Client
36
+
37
+ The API exposes thread state/message/thread operations under `/v1/threads...` routes in the checkpointer router. The TypeScript client wraps these with methods such as:
38
+
39
+ - `threadState`
40
+ - `updateThreadState`
41
+ - `clearThreadState`
42
+ - `threadDetails`
43
+ - `threads`
44
+ - `threadMessages`
45
+ - `addThreadMessages`
46
+ - `singleMessage`
47
+ - `deleteMessage`
48
+ - `deleteThread`
49
+
50
+ ## Rules
51
+
52
+ - Always preserve `thread_id` across a conversation.
53
+ - Use `PgCheckpointer` or equivalent durable storage for multi-worker production.
54
+ - Store conversation continuity in the checkpointer, not the memory store.
55
+ - Use `aclean_thread`/delete APIs when removing a thread so state, messages, and metadata stay consistent.
56
+
57
+ ## Source Map
58
+
59
+ - Base API: https://github.com/10xGraph/10xGraph/blob/main/tenxgraph/storage/checkpointer/base_checkpointer.py
60
+ - In-memory backend: https://github.com/10xGraph/10xGraph/blob/main/tenxgraph/storage/checkpointer/in_memory_checkpointer.py
61
+ - Postgres backend: https://github.com/10xGraph/10xGraph/blob/main/tenxgraph/storage/checkpointer/pg_checkpointer.py
62
+ - API router: https://github.com/10xGraph/10xgraph-api/tree/main/tenxgraph_api/src/app/routers/checkpointer
63
+ - TS endpoints: https://github.com/10xHub/agentflow-client/tree/main/src/endpoints
@@ -0,0 +1,73 @@
1
+ # CLI Commands
2
+
3
+ Use this when changing `10xgraph-api` command behavior, generated files, or deployment scaffolding.
4
+
5
+ ## Package
6
+
7
+ Install:
8
+
9
+ ```bash
10
+ pip install 10xgraph-api
11
+ ```
12
+
13
+ Entry point:
14
+
15
+ ```text
16
+ 10xgraph = tenxgraph_api.cli.main:main
17
+ agentflow = tenxgraph_api.cli.main:legacy_main # deprecated alias, removed in 2.0
18
+ ```
19
+
20
+ ## Commands
21
+
22
+ `10xgraph init`
23
+
24
+ - Scaffolds `10xgraph.json`, `graph/__init__.py`, and `graph/react.py`, and suggests `10xgraph skills` as a next step.
25
+ - Options include `--path/-p`, `--force/-f`, `--prod`, `--verbose/-v`, and `--quiet/-q`.
26
+ - `--prod` also adds production project files such as `pyproject.toml` and `.pre-commit-config.yaml`.
27
+
28
+ `10xgraph api`
29
+
30
+ - Starts the FastAPI server for a compiled graph.
31
+ - Options include `--config/-c`, `--host/-H`, `--port/-p`, `--reload/--no-reload`, `--verbose/-v`, and `--quiet/-q`.
32
+ - Defaults are config `10xgraph.json`, host `127.0.0.1`, port `8000`, reload enabled.
33
+
34
+ `10xgraph play`
35
+
36
+ - Starts the API server and opens/prints the hosted playground URL.
37
+ - Accepts the same server options as `api`.
38
+ - Uses host/port to build the playground backend URL.
39
+
40
+ `10xgraph build`
41
+
42
+ - Generates Docker deployment files.
43
+ - Options include `--output/-o`, `--force/-f`, `--python-version`, `--port/-p`, `--docker-compose/--no-docker-compose`, `--service-name`, `--verbose/-v`, and `--quiet/-q`.
44
+
45
+ `10xgraph skills`
46
+
47
+ - Installs the bundled 10xGraph skill (an Agent Skills spec folder: `SKILL.md` + `references/`) into an agent-specific project directory. Every agent gets the same folder; paths inside it are relative to the skill directory.
48
+ - Prompts for the target agent when `--agent` is omitted:
49
+ - `1` / `codex`: `.agents/skills/10xgraph`
50
+ - `2` / `claude`: `.claude/skills/10xgraph`
51
+ - `3` / `github`: `.github/instructions/10xgraph.instructions.md` and `.github/skills/10xgraph`
52
+ - Options include `--agent/-a`, `--path/-p`, `--force/-f`, `--all`, `--list/-l`, `--verbose/-v`, and `--quiet/-q`.
53
+ - `--validate PATH` (repeatable) checks a skill directory, or a folder of skill directories, against the Agent Skills specification (https://agentskills.io/specification) and exits non-zero on errors. Nothing is installed.
54
+ - Source templates: https://github.com/10xGraph/10xgraph-api/tree/main/tenxgraph_api/cli/templates/skills
55
+
56
+ `10xgraph version`
57
+
58
+ - Prints CLI and library version information.
59
+
60
+ ## Rules
61
+
62
+ - Use docs package names in user-facing text.
63
+ - Keep command options aligned with https://10xgraph.com/
64
+ - If command defaults change, update docs, templates, and tests together.
65
+ - Generated skill templates live under https://github.com/10xGraph/10xgraph-api/tree/main/tenxgraph_api/cli/templates/skills
66
+
67
+ ## Source Map
68
+
69
+ - CLI main: https://github.com/10xGraph/10xgraph-api/blob/main/tenxgraph_api/cli/main.py
70
+ - Commands: https://github.com/10xGraph/10xgraph-api/tree/main/tenxgraph_api/cli/commands
71
+ - CLI config/output/validation: https://github.com/10xGraph/10xgraph-api/tree/main/tenxgraph_api/cli/core
72
+ - Templates: https://github.com/10xGraph/10xgraph-api/tree/main/tenxgraph_api/cli/templates
73
+ - Docs: https://10xgraph.com/