remdb 0.3.7__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 (187) hide show
  1. rem/__init__.py +2 -0
  2. rem/agentic/README.md +650 -0
  3. rem/agentic/__init__.py +39 -0
  4. rem/agentic/agents/README.md +155 -0
  5. rem/agentic/agents/__init__.py +8 -0
  6. rem/agentic/context.py +148 -0
  7. rem/agentic/context_builder.py +329 -0
  8. rem/agentic/mcp/__init__.py +0 -0
  9. rem/agentic/mcp/tool_wrapper.py +107 -0
  10. rem/agentic/otel/__init__.py +5 -0
  11. rem/agentic/otel/setup.py +151 -0
  12. rem/agentic/providers/phoenix.py +674 -0
  13. rem/agentic/providers/pydantic_ai.py +572 -0
  14. rem/agentic/query.py +117 -0
  15. rem/agentic/query_helper.py +89 -0
  16. rem/agentic/schema.py +396 -0
  17. rem/agentic/serialization.py +245 -0
  18. rem/agentic/tools/__init__.py +5 -0
  19. rem/agentic/tools/rem_tools.py +231 -0
  20. rem/api/README.md +420 -0
  21. rem/api/main.py +324 -0
  22. rem/api/mcp_router/prompts.py +182 -0
  23. rem/api/mcp_router/resources.py +536 -0
  24. rem/api/mcp_router/server.py +213 -0
  25. rem/api/mcp_router/tools.py +584 -0
  26. rem/api/routers/auth.py +229 -0
  27. rem/api/routers/chat/__init__.py +5 -0
  28. rem/api/routers/chat/completions.py +281 -0
  29. rem/api/routers/chat/json_utils.py +76 -0
  30. rem/api/routers/chat/models.py +124 -0
  31. rem/api/routers/chat/streaming.py +185 -0
  32. rem/auth/README.md +258 -0
  33. rem/auth/__init__.py +26 -0
  34. rem/auth/middleware.py +100 -0
  35. rem/auth/providers/__init__.py +13 -0
  36. rem/auth/providers/base.py +376 -0
  37. rem/auth/providers/google.py +163 -0
  38. rem/auth/providers/microsoft.py +237 -0
  39. rem/cli/README.md +455 -0
  40. rem/cli/__init__.py +8 -0
  41. rem/cli/commands/README.md +126 -0
  42. rem/cli/commands/__init__.py +3 -0
  43. rem/cli/commands/ask.py +566 -0
  44. rem/cli/commands/configure.py +497 -0
  45. rem/cli/commands/db.py +493 -0
  46. rem/cli/commands/dreaming.py +324 -0
  47. rem/cli/commands/experiments.py +1302 -0
  48. rem/cli/commands/mcp.py +66 -0
  49. rem/cli/commands/process.py +245 -0
  50. rem/cli/commands/schema.py +183 -0
  51. rem/cli/commands/serve.py +106 -0
  52. rem/cli/dreaming.py +363 -0
  53. rem/cli/main.py +96 -0
  54. rem/config.py +237 -0
  55. rem/mcp_server.py +41 -0
  56. rem/models/core/__init__.py +49 -0
  57. rem/models/core/core_model.py +64 -0
  58. rem/models/core/engram.py +333 -0
  59. rem/models/core/experiment.py +628 -0
  60. rem/models/core/inline_edge.py +132 -0
  61. rem/models/core/rem_query.py +243 -0
  62. rem/models/entities/__init__.py +43 -0
  63. rem/models/entities/file.py +57 -0
  64. rem/models/entities/image_resource.py +88 -0
  65. rem/models/entities/message.py +35 -0
  66. rem/models/entities/moment.py +123 -0
  67. rem/models/entities/ontology.py +191 -0
  68. rem/models/entities/ontology_config.py +131 -0
  69. rem/models/entities/resource.py +95 -0
  70. rem/models/entities/schema.py +87 -0
  71. rem/models/entities/user.py +85 -0
  72. rem/py.typed +0 -0
  73. rem/schemas/README.md +507 -0
  74. rem/schemas/__init__.py +6 -0
  75. rem/schemas/agents/README.md +92 -0
  76. rem/schemas/agents/core/moment-builder.yaml +178 -0
  77. rem/schemas/agents/core/rem-query-agent.yaml +226 -0
  78. rem/schemas/agents/core/resource-affinity-assessor.yaml +99 -0
  79. rem/schemas/agents/core/simple-assistant.yaml +19 -0
  80. rem/schemas/agents/core/user-profile-builder.yaml +163 -0
  81. rem/schemas/agents/examples/contract-analyzer.yaml +317 -0
  82. rem/schemas/agents/examples/contract-extractor.yaml +134 -0
  83. rem/schemas/agents/examples/cv-parser.yaml +263 -0
  84. rem/schemas/agents/examples/hello-world.yaml +37 -0
  85. rem/schemas/agents/examples/query.yaml +54 -0
  86. rem/schemas/agents/examples/simple.yaml +21 -0
  87. rem/schemas/agents/examples/test.yaml +29 -0
  88. rem/schemas/agents/rem.yaml +128 -0
  89. rem/schemas/evaluators/hello-world/default.yaml +77 -0
  90. rem/schemas/evaluators/rem/faithfulness.yaml +219 -0
  91. rem/schemas/evaluators/rem/lookup-correctness.yaml +182 -0
  92. rem/schemas/evaluators/rem/retrieval-precision.yaml +199 -0
  93. rem/schemas/evaluators/rem/retrieval-recall.yaml +211 -0
  94. rem/schemas/evaluators/rem/search-correctness.yaml +192 -0
  95. rem/services/__init__.py +16 -0
  96. rem/services/audio/INTEGRATION.md +308 -0
  97. rem/services/audio/README.md +376 -0
  98. rem/services/audio/__init__.py +15 -0
  99. rem/services/audio/chunker.py +354 -0
  100. rem/services/audio/transcriber.py +259 -0
  101. rem/services/content/README.md +1269 -0
  102. rem/services/content/__init__.py +5 -0
  103. rem/services/content/providers.py +801 -0
  104. rem/services/content/service.py +676 -0
  105. rem/services/dreaming/README.md +230 -0
  106. rem/services/dreaming/__init__.py +53 -0
  107. rem/services/dreaming/affinity_service.py +336 -0
  108. rem/services/dreaming/moment_service.py +264 -0
  109. rem/services/dreaming/ontology_service.py +54 -0
  110. rem/services/dreaming/user_model_service.py +297 -0
  111. rem/services/dreaming/utils.py +39 -0
  112. rem/services/embeddings/__init__.py +11 -0
  113. rem/services/embeddings/api.py +120 -0
  114. rem/services/embeddings/worker.py +421 -0
  115. rem/services/fs/README.md +662 -0
  116. rem/services/fs/__init__.py +62 -0
  117. rem/services/fs/examples.py +206 -0
  118. rem/services/fs/examples_paths.py +204 -0
  119. rem/services/fs/git_provider.py +935 -0
  120. rem/services/fs/local_provider.py +760 -0
  121. rem/services/fs/parsing-hooks-examples.md +172 -0
  122. rem/services/fs/paths.py +276 -0
  123. rem/services/fs/provider.py +460 -0
  124. rem/services/fs/s3_provider.py +1042 -0
  125. rem/services/fs/service.py +186 -0
  126. rem/services/git/README.md +1075 -0
  127. rem/services/git/__init__.py +17 -0
  128. rem/services/git/service.py +469 -0
  129. rem/services/phoenix/EXPERIMENT_DESIGN.md +1146 -0
  130. rem/services/phoenix/README.md +453 -0
  131. rem/services/phoenix/__init__.py +46 -0
  132. rem/services/phoenix/client.py +686 -0
  133. rem/services/phoenix/config.py +88 -0
  134. rem/services/phoenix/prompt_labels.py +477 -0
  135. rem/services/postgres/README.md +575 -0
  136. rem/services/postgres/__init__.py +23 -0
  137. rem/services/postgres/migration_service.py +427 -0
  138. rem/services/postgres/pydantic_to_sqlalchemy.py +232 -0
  139. rem/services/postgres/register_type.py +352 -0
  140. rem/services/postgres/repository.py +337 -0
  141. rem/services/postgres/schema_generator.py +379 -0
  142. rem/services/postgres/service.py +802 -0
  143. rem/services/postgres/sql_builder.py +354 -0
  144. rem/services/rem/README.md +304 -0
  145. rem/services/rem/__init__.py +23 -0
  146. rem/services/rem/exceptions.py +71 -0
  147. rem/services/rem/executor.py +293 -0
  148. rem/services/rem/parser.py +145 -0
  149. rem/services/rem/queries.py +196 -0
  150. rem/services/rem/query.py +371 -0
  151. rem/services/rem/service.py +527 -0
  152. rem/services/session/README.md +374 -0
  153. rem/services/session/__init__.py +6 -0
  154. rem/services/session/compression.py +360 -0
  155. rem/services/session/reload.py +77 -0
  156. rem/settings.py +1235 -0
  157. rem/sql/002_install_models.sql +1068 -0
  158. rem/sql/background_indexes.sql +42 -0
  159. rem/sql/install_models.sql +1038 -0
  160. rem/sql/migrations/001_install.sql +503 -0
  161. rem/sql/migrations/002_install_models.sql +1202 -0
  162. rem/utils/AGENTIC_CHUNKING.md +597 -0
  163. rem/utils/README.md +583 -0
  164. rem/utils/__init__.py +43 -0
  165. rem/utils/agentic_chunking.py +622 -0
  166. rem/utils/batch_ops.py +343 -0
  167. rem/utils/chunking.py +108 -0
  168. rem/utils/clip_embeddings.py +276 -0
  169. rem/utils/dict_utils.py +98 -0
  170. rem/utils/embeddings.py +423 -0
  171. rem/utils/examples/embeddings_example.py +305 -0
  172. rem/utils/examples/sql_types_example.py +202 -0
  173. rem/utils/markdown.py +16 -0
  174. rem/utils/model_helpers.py +236 -0
  175. rem/utils/schema_loader.py +336 -0
  176. rem/utils/sql_types.py +348 -0
  177. rem/utils/user_id.py +81 -0
  178. rem/utils/vision.py +330 -0
  179. rem/workers/README.md +506 -0
  180. rem/workers/__init__.py +5 -0
  181. rem/workers/dreaming.py +502 -0
  182. rem/workers/engram_processor.py +312 -0
  183. rem/workers/sqs_file_processor.py +193 -0
  184. remdb-0.3.7.dist-info/METADATA +1473 -0
  185. remdb-0.3.7.dist-info/RECORD +187 -0
  186. remdb-0.3.7.dist-info/WHEEL +4 -0
  187. remdb-0.3.7.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,89 @@
1
+ """
2
+ Helper functions for REM Query Agent.
3
+
4
+ This module provides convenience functions that load the REM Query Agent
5
+ from YAML schema and execute queries.
6
+ """
7
+
8
+ from typing import Any
9
+
10
+ from pydantic import BaseModel
11
+
12
+ from .context import AgentContext
13
+ from .providers.pydantic_ai import create_agent_from_schema_file
14
+
15
+
16
+ class REMQueryOutput(BaseModel):
17
+ """
18
+ REM Query Agent structured output.
19
+
20
+ Matches the schema defined in schemas/agents/core/rem-query-agent.yaml
21
+ """
22
+
23
+ query: str
24
+ confidence: float
25
+ reasoning: str = ""
26
+
27
+
28
+ async def ask_rem(
29
+ natural_query: str,
30
+ user_id: str = "system",
31
+ llm_model: str | None = None,
32
+ ) -> REMQueryOutput:
33
+ """
34
+ Convert natural language query to structured REM query.
35
+
36
+ Loads the REM Query Agent from YAML schema and executes the query.
37
+
38
+ Args:
39
+ natural_query: User's question in natural language
40
+ user_id: User ID for context (defaults to "system")
41
+ llm_model: Optional LLM model override
42
+
43
+ Returns:
44
+ REMQueryOutput with query, confidence, and reasoning
45
+
46
+ Example:
47
+ result = await ask_rem("Show me Sarah Chen")
48
+ # REMQueryOutput(
49
+ # query="LOOKUP sarah-chen",
50
+ # confidence=1.0,
51
+ # reasoning=""
52
+ # )
53
+ """
54
+ # Create context (only pass default_model if llm_model is provided)
55
+ context_kwargs = {"user_id": user_id}
56
+ if llm_model is not None:
57
+ context_kwargs["default_model"] = llm_model
58
+ context = AgentContext(**context_kwargs)
59
+
60
+ # Load agent from YAML schema
61
+ agent = await create_agent_from_schema_file(
62
+ schema_name_or_path="rem-query-agent",
63
+ context=context,
64
+ model_override=llm_model, # type: ignore[arg-type]
65
+ )
66
+
67
+ # Run query
68
+ result = await agent.run(natural_query)
69
+
70
+ # Handle different Pydantic AI versions
71
+ if hasattr(result, "data"):
72
+ output = result.data
73
+ elif hasattr(result, "output"):
74
+ output = result.output
75
+ else:
76
+ output = result
77
+
78
+ # Convert to REMQueryOutput if not already
79
+ if isinstance(output, dict):
80
+ return REMQueryOutput(**output)
81
+ elif isinstance(output, REMQueryOutput):
82
+ return output
83
+ else:
84
+ # Fallback: try to extract fields
85
+ return REMQueryOutput(
86
+ query=getattr(output, "query", str(output)),
87
+ confidence=getattr(output, "confidence", 0.5),
88
+ reasoning=getattr(output, "reasoning", ""),
89
+ )
rem/agentic/schema.py ADDED
@@ -0,0 +1,396 @@
1
+ """
2
+ Agent Schema Protocol - Pydantic models for REM agent schemas.
3
+
4
+ This module defines the structure of agent schemas used in REM.
5
+ Agent schemas are JSON Schema documents with REM-specific extensions
6
+ in the `json_schema_extra` field.
7
+
8
+ The schema protocol serves as:
9
+ 1. Documentation for agent schema structure
10
+ 2. Validation for agent schema files
11
+ 3. Type hints for schema manipulation
12
+ 4. Single source of truth for schema conventions
13
+ """
14
+
15
+ from typing import Any, Literal
16
+ from pydantic import BaseModel, Field
17
+
18
+
19
+ class MCPToolReference(BaseModel):
20
+ """
21
+ Reference to an MCP tool available to the agent.
22
+
23
+ Tools are functions that agents can call during execution to
24
+ interact with external systems, retrieve data, or perform actions.
25
+
26
+ Example:
27
+ {
28
+ "name": "lookup_entity",
29
+ "mcp_server": "rem",
30
+ "description": "Lookup entities by exact key with O(1) performance"
31
+ }
32
+ """
33
+
34
+ name: str = Field(
35
+ description=(
36
+ "Tool name as defined in the MCP server. "
37
+ "Must match the tool name exposed by the MCP server exactly."
38
+ )
39
+ )
40
+
41
+ mcp_server: str = Field(
42
+ description=(
43
+ "MCP server identifier. Resolved via environment variable: "
44
+ "MCP_SERVER_{NAME} or MCP__{NAME}__URL. "
45
+ "Common values: 'rem' (REM knowledge graph), 'filesystem', 'web'."
46
+ )
47
+ )
48
+
49
+ description: str | None = Field(
50
+ default=None,
51
+ description=(
52
+ "Optional description override. If provided, replaces the tool's "
53
+ "description from the MCP server in the agent's context. "
54
+ "Use this to provide agent-specific guidance on tool usage."
55
+ ),
56
+ )
57
+
58
+
59
+ class MCPResourceReference(BaseModel):
60
+ """
61
+ Reference to MCP resources accessible to the agent.
62
+
63
+ Resources are data sources that can be read by agents, such as
64
+ knowledge graph entities, files, or API endpoints.
65
+
66
+ Example:
67
+ {
68
+ "uri_pattern": "rem://resources/.*",
69
+ "mcp_server": "rem"
70
+ }
71
+ """
72
+
73
+ uri_pattern: str = Field(
74
+ description=(
75
+ "Regex pattern matching resource URIs. "
76
+ "Examples: "
77
+ "'rem://resources/.*' (all resources), "
78
+ "'rem://moments/.*' (all moments), "
79
+ "'file:///data/.*' (local files). "
80
+ "Supports full regex syntax for flexible matching."
81
+ )
82
+ )
83
+
84
+ mcp_server: str = Field(
85
+ description=(
86
+ "MCP server identifier that provides these resources. "
87
+ "Resolved via environment variable MCP_SERVER_{NAME}. "
88
+ "The server must expose resources matching the uri_pattern."
89
+ )
90
+ )
91
+
92
+
93
+ class AgentSchemaMetadata(BaseModel):
94
+ """
95
+ REM-specific metadata for agent schemas.
96
+
97
+ This is stored in the `json_schema_extra` field of the JSON Schema
98
+ and extends standard JSON Schema with REM agent conventions.
99
+
100
+ All fields are optional but recommended for production agents.
101
+ """
102
+
103
+ kind: str | None = Field(
104
+ default=None,
105
+ description=(
106
+ "Schema kind/type. Determines how the schema is processed. "
107
+ "Values: 'agent', 'evaluator', 'engram'. "
108
+ "Examples: 'agent' for agents, 'evaluator' for LLM-as-a-Judge evaluators, "
109
+ "'engram' for memory documents. "
110
+ "Used by processors to route schemas to the correct handler."
111
+ )
112
+ )
113
+
114
+ name: str = Field(
115
+ description=(
116
+ "Unique schema identifier (kebab-case). "
117
+ "Examples: 'query-agent', 'cv-parser', 'rem-lookup-correctness'. "
118
+ "Used in URLs, file paths, database keys, and references. "
119
+ "Must be unique within the kind namespace."
120
+ ),
121
+ )
122
+
123
+ version: str | None = Field(
124
+ default=None,
125
+ description=(
126
+ "Semantic version of the agent schema. "
127
+ "Format: 'MAJOR.MINOR.PATCH' (e.g., '1.0.0', '2.1.3'). "
128
+ "Increment MAJOR for breaking changes, MINOR for new features, "
129
+ "PATCH for bug fixes. Used for schema evolution and compatibility."
130
+ ),
131
+ )
132
+
133
+ tools: list[MCPToolReference] = Field(
134
+ default_factory=list,
135
+ description=(
136
+ "MCP tools available to the agent. "
137
+ "Tools are loaded dynamically from MCP servers at agent creation time. "
138
+ "The agent can call these tools during execution to retrieve data, "
139
+ "perform actions, or interact with external systems."
140
+ ),
141
+ )
142
+
143
+ resources: list[MCPResourceReference] = Field(
144
+ default_factory=list,
145
+ description=(
146
+ "MCP resources accessible to the agent. "
147
+ "Resources are data sources that can be read by the agent, "
148
+ "such as knowledge graph entities, files, or API endpoints. "
149
+ "URI patterns are matched against resource URIs to determine access."
150
+ ),
151
+ )
152
+
153
+ tags: list[str] = Field(
154
+ default_factory=list,
155
+ description=(
156
+ "Categorization tags for the agent. "
157
+ "Examples: ['query', 'knowledge-graph'], ['summarization', 'nlp']. "
158
+ "Used for discovery, filtering, and organization of agents."
159
+ ),
160
+ )
161
+
162
+ author: str | None = Field(
163
+ default=None,
164
+ description=(
165
+ "Agent author or team. "
166
+ "Examples: 'REM Team', 'john@example.com'. "
167
+ "Used for attribution and maintenance tracking."
168
+ ),
169
+ )
170
+
171
+ override_temperature: float | None = Field(
172
+ default=None,
173
+ description=(
174
+ "Override default LLM temperature (0.0-1.0) for this agent. "
175
+ "If None, uses global settings.llm.default_temperature."
176
+ ),
177
+ )
178
+
179
+ override_max_iterations: int | None = Field(
180
+ default=None,
181
+ description=(
182
+ "Override maximum iterations for this agent. "
183
+ "If None, uses global settings.llm.default_max_iterations."
184
+ ),
185
+ )
186
+
187
+ model_config = {"extra": "allow"} # Allow additional custom metadata
188
+
189
+
190
+ class AgentSchema(BaseModel):
191
+ """
192
+ Complete REM agent schema following JSON Schema Draft 7.
193
+
194
+ Agent schemas are JSON Schema documents that define:
195
+ 1. System prompt (in `description` field)
196
+ 2. Structured output format (in `properties` field)
197
+ 3. REM-specific metadata (in `json_schema_extra` field)
198
+
199
+ This is the single source of truth for agent behavior, output structure,
200
+ and available tools/resources.
201
+
202
+ Design Pattern:
203
+ - JSON Schema as the schema language (framework-agnostic)
204
+ - System prompt embedded in description (visible to LLM)
205
+ - Output structure as standard JSON Schema properties
206
+ - REM extensions in json_schema_extra (invisible to LLM)
207
+
208
+ Example:
209
+ ```json
210
+ {
211
+ "type": "object",
212
+ "description": "You are a Query Agent that answers questions...",
213
+ "properties": {
214
+ "answer": {"type": "string", "description": "Query answer"},
215
+ "confidence": {"type": "number", "minimum": 0, "maximum": 1}
216
+ },
217
+ "required": ["answer", "confidence"],
218
+ "json_schema_extra": {
219
+ "kind": "agent",
220
+ "name": "query-agent",
221
+ "version": "1.0.0",
222
+ "tools": [{"name": "lookup_entity", "mcp_server": "rem"}]
223
+ }
224
+ }
225
+ ```
226
+ """
227
+
228
+ type: Literal["object"] = Field(
229
+ default="object",
230
+ description="JSON Schema type. Must be 'object' for agent schemas.",
231
+ )
232
+
233
+ description: str = Field(
234
+ description=(
235
+ "System prompt for the agent. This is the primary instruction "
236
+ "given to the LLM explaining:\n"
237
+ "- Agent's role and purpose\n"
238
+ "- Available capabilities\n"
239
+ "- Workflow and reasoning steps\n"
240
+ "- Guidelines and constraints\n"
241
+ "- Output format expectations\n\n"
242
+ "This field is visible to the LLM and should be comprehensive, "
243
+ "clear, and actionable. Use markdown formatting for structure."
244
+ )
245
+ )
246
+
247
+ properties: dict[str, Any] = Field(
248
+ description=(
249
+ "Output schema properties following JSON Schema Draft 7. "
250
+ "Each property defines:\n"
251
+ "- type: JSON type (string, number, boolean, array, object)\n"
252
+ "- description: Field purpose and content guidance\n"
253
+ "- Validation: minimum, maximum, pattern, enum, etc.\n\n"
254
+ "These properties define the structured output the agent produces. "
255
+ "The agent must return a JSON object matching this schema."
256
+ )
257
+ )
258
+
259
+ required: list[str] = Field(
260
+ default_factory=list,
261
+ description=(
262
+ "List of required property names. "
263
+ "The agent must include these fields in its output. "
264
+ "Optional fields can be omitted. "
265
+ "Example: ['answer', 'confidence']"
266
+ ),
267
+ )
268
+
269
+ json_schema_extra: AgentSchemaMetadata | dict[str, Any] = Field(
270
+ default_factory=dict,
271
+ description=(
272
+ "REM-specific metadata extending JSON Schema. "
273
+ "Contains agent identification, versioning, and MCP configuration. "
274
+ "This field is not visible to the LLM - it's used by the REM system "
275
+ "for agent creation, tool loading, and resource access control."
276
+ ),
277
+ )
278
+
279
+ # Additional JSON Schema fields (optional)
280
+ title: str | None = Field(
281
+ default=None,
282
+ description="Schema title. If not provided, derived from name.",
283
+ )
284
+
285
+ definitions: dict[str, Any] | None = Field(
286
+ default=None,
287
+ description=(
288
+ "Reusable schema definitions for complex nested types. "
289
+ "Use JSON Schema $ref to reference definitions. "
290
+ "Example: {'EntityKey': {'type': 'string', 'pattern': '^[a-z0-9-]+$'}}"
291
+ ),
292
+ )
293
+
294
+ additionalProperties: bool = Field(
295
+ default=False,
296
+ description=(
297
+ "Whether to allow additional properties not defined in schema. "
298
+ "Default: False (strict validation). Set to True for flexible schemas."
299
+ ),
300
+ )
301
+
302
+ model_config = {"extra": "allow"} # Support full JSON Schema extensions
303
+
304
+
305
+ # Convenience type aliases for common use cases
306
+ AgentSchemaDict = dict[str, Any] # Raw JSON Schema dict
307
+ AgentSchemaJSON = str # JSON-serialized schema
308
+
309
+
310
+ def validate_agent_schema(schema: dict[str, Any]) -> AgentSchema:
311
+ """
312
+ Validate agent schema structure.
313
+
314
+ Args:
315
+ schema: Raw agent schema dict
316
+
317
+ Returns:
318
+ Validated AgentSchema instance
319
+
320
+ Raises:
321
+ ValidationError: If schema is invalid
322
+
323
+ Example:
324
+ >>> schema = load_schema("agents/query_agent.json")
325
+ >>> validated = validate_agent_schema(schema)
326
+ >>> print(validated.json_schema_extra["name"])
327
+ "query-agent"
328
+ """
329
+ return AgentSchema.model_validate(schema)
330
+
331
+
332
+ def create_agent_schema(
333
+ description: str,
334
+ properties: dict[str, Any],
335
+ required: list[str],
336
+ name: str,
337
+ kind: str | None = None,
338
+ tools: list[dict[str, Any]] | None = None,
339
+ resources: list[dict[str, Any]] | None = None,
340
+ version: str = "1.0.0",
341
+ override_temperature: float | None = None,
342
+ override_max_iterations: int | None = None,
343
+ **kwargs,
344
+ ) -> AgentSchema:
345
+ """
346
+ Create agent schema programmatically.
347
+
348
+ Args:
349
+ description: System prompt
350
+ properties: Output schema properties
351
+ required: Required field names
352
+ name: Schema name in kebab-case (e.g., 'query-agent')
353
+ kind: Schema kind ('agent' or 'evaluator'), optional
354
+ tools: MCP tool references
355
+ resources: MCP resource patterns
356
+ version: Schema version
357
+ override_temperature: Override default LLM temperature for this agent.
358
+ override_max_iterations: Override maximum iterations for this agent.
359
+ **kwargs: Additional JSON Schema fields
360
+
361
+ Returns:
362
+ AgentSchema instance
363
+
364
+ Example:
365
+ >>> schema = create_agent_schema(
366
+ ... description="You are a helpful assistant...",
367
+ ... properties={
368
+ ... "answer": {"type": "string", "description": "Response"},
369
+ ... "confidence": {"type": "number", "minimum": 0, "maximum": 1}
370
+ ... },
371
+ ... required=["answer"],
372
+ ... kind="agent",
373
+ ... name="assistant",
374
+ ... tools=[{"name": "search", "mcp_server": "rem"}],
375
+ ... version="1.0.0"
376
+ ... )
377
+ >>> schema.json_schema_extra["tools"][0]["name"]
378
+ "search"
379
+ """
380
+ metadata = AgentSchemaMetadata(
381
+ kind=kind,
382
+ name=name,
383
+ tools=[MCPToolReference.model_validate(t) for t in (tools or [])],
384
+ resources=[MCPResourceReference.model_validate(r) for r in (resources or [])],
385
+ version=version,
386
+ override_temperature=override_temperature,
387
+ override_max_iterations=override_max_iterations,
388
+ )
389
+
390
+ return AgentSchema(
391
+ description=description,
392
+ properties=properties,
393
+ required=required,
394
+ json_schema_extra=metadata.model_dump(),
395
+ **kwargs,
396
+ )