agenta 0.48.9__py3-none-any.whl → 0.48.10__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.

Potentially problematic release.


This version of agenta might be problematic. Click here for more details.

Files changed (295) hide show
  1. agenta/__init__.py +3 -2
  2. agenta/client/Readme.md +258 -80
  3. agenta/client/__init__.py +205 -29
  4. agenta/client/backend/__init__.py +461 -0
  5. agenta/client/backend/access_control/__init__.py +2 -0
  6. agenta/client/backend/access_control/client.py +53 -73
  7. agenta/client/backend/access_control/raw_client.py +180 -0
  8. agenta/client/backend/admin/__init__.py +2 -0
  9. agenta/client/backend/admin/client.py +473 -268
  10. agenta/client/backend/admin/raw_client.py +1017 -0
  11. agenta/client/backend/api_keys/__init__.py +2 -0
  12. agenta/client/backend/api_keys/client.py +43 -276
  13. agenta/client/backend/api_keys/raw_client.py +364 -0
  14. agenta/client/backend/apps/__init__.py +2 -0
  15. agenta/client/backend/apps/client.py +132 -895
  16. agenta/client/backend/apps/raw_client.py +1516 -0
  17. agenta/client/backend/bases/__init__.py +2 -0
  18. agenta/client/backend/bases/client.py +33 -73
  19. agenta/client/backend/bases/raw_client.py +179 -0
  20. agenta/client/backend/billing/__init__.py +3 -0
  21. agenta/client/backend/billing/client.py +564 -0
  22. agenta/client/backend/billing/raw_client.py +805 -0
  23. agenta/client/backend/client.py +1268 -0
  24. agenta/client/backend/configs/__init__.py +2 -0
  25. agenta/client/backend/configs/client.py +49 -361
  26. agenta/client/backend/configs/raw_client.py +402 -0
  27. agenta/client/backend/containers/__init__.py +1 -3
  28. agenta/client/backend/containers/client.py +25 -548
  29. agenta/client/backend/containers/raw_client.py +112 -0
  30. agenta/client/backend/core/__init__.py +5 -0
  31. agenta/client/backend/core/api_error.py +12 -6
  32. agenta/client/backend/core/client_wrapper.py +4 -4
  33. agenta/client/backend/core/file.py +1 -3
  34. agenta/client/backend/core/force_multipart.py +16 -0
  35. agenta/client/backend/core/http_client.py +78 -34
  36. agenta/client/backend/core/http_response.py +55 -0
  37. agenta/client/backend/core/jsonable_encoder.py +0 -1
  38. agenta/client/backend/core/pydantic_utilities.py +88 -113
  39. agenta/client/backend/core/serialization.py +9 -3
  40. agenta/client/backend/environment.py +7 -0
  41. agenta/client/backend/environments/__init__.py +2 -0
  42. agenta/client/backend/environments/client.py +43 -79
  43. agenta/client/backend/environments/raw_client.py +193 -0
  44. agenta/client/backend/errors/__init__.py +2 -0
  45. agenta/client/backend/errors/unprocessable_entity_error.py +8 -2
  46. agenta/client/backend/evals/__init__.py +3 -0
  47. agenta/client/backend/evals/client.py +1042 -0
  48. agenta/client/backend/evals/raw_client.py +1549 -0
  49. agenta/client/backend/evaluations/__init__.py +2 -0
  50. agenta/client/backend/evaluations/client.py +106 -590
  51. agenta/client/backend/evaluations/raw_client.py +1344 -0
  52. agenta/client/backend/evaluators/__init__.py +2 -0
  53. agenta/client/backend/evaluators/client.py +99 -516
  54. agenta/client/backend/evaluators/raw_client.py +1182 -0
  55. agenta/client/backend/human_evaluations/__init__.py +2 -0
  56. agenta/client/backend/human_evaluations/client.py +120 -680
  57. agenta/client/backend/human_evaluations/raw_client.py +1577 -0
  58. agenta/client/backend/observability/__init__.py +14 -2
  59. agenta/client/backend/observability/client.py +185 -341
  60. agenta/client/backend/observability/raw_client.py +943 -0
  61. agenta/client/backend/observability/types/__init__.py +10 -2
  62. agenta/client/backend/observability/types/{format.py → fetch_trace_by_id_request_trace_id.py} +1 -1
  63. agenta/client/backend/observability/types/fetch_trace_by_id_response.py +15 -0
  64. agenta/client/backend/observability/types/query_analytics_response.py +2 -1
  65. agenta/client/backend/observability/types/query_traces_response.py +7 -3
  66. agenta/client/backend/organization/__init__.py +2 -0
  67. agenta/client/backend/organization/client.py +105 -361
  68. agenta/client/backend/organization/raw_client.py +774 -0
  69. agenta/client/backend/raw_client.py +1432 -0
  70. agenta/client/backend/scopes/__init__.py +2 -0
  71. agenta/client/backend/scopes/client.py +31 -45
  72. agenta/client/backend/scopes/raw_client.py +105 -0
  73. agenta/client/backend/testsets/__init__.py +14 -0
  74. agenta/client/backend/testsets/client.py +1098 -653
  75. agenta/client/backend/testsets/raw_client.py +2348 -0
  76. agenta/client/backend/testsets/types/__init__.py +17 -0
  77. agenta/client/backend/testsets/types/create_testset_from_file_request_file_type.py +7 -0
  78. agenta/client/backend/testsets/types/fetch_testset_to_file_request_file_type.py +7 -0
  79. agenta/client/backend/testsets/types/update_testset_from_file_request_file_type.py +7 -0
  80. agenta/client/backend/tracing/__init__.py +7 -0
  81. agenta/client/backend/tracing/client.py +782 -0
  82. agenta/client/backend/tracing/raw_client.py +1223 -0
  83. agenta/client/backend/tracing/types/__init__.py +8 -0
  84. agenta/client/backend/{types/variant_action_enum.py → tracing/types/fetch_trace_request_trace_id.py} +1 -1
  85. agenta/client/backend/tracing/types/remove_trace_request_trace_id.py +5 -0
  86. agenta/client/backend/types/__init__.py +153 -26
  87. agenta/client/backend/types/account_request.py +24 -0
  88. agenta/client/backend/types/account_response.py +5 -7
  89. agenta/client/backend/types/agenta_node_dto.py +13 -13
  90. agenta/client/backend/types/agenta_node_dto_nodes_value.py +1 -0
  91. agenta/client/backend/types/agenta_nodes_response.py +14 -8
  92. agenta/client/backend/types/agenta_root_dto.py +16 -8
  93. agenta/client/backend/types/agenta_roots_response.py +16 -8
  94. agenta/client/backend/types/agenta_tree_dto.py +16 -8
  95. agenta/client/backend/types/agenta_trees_response.py +16 -8
  96. agenta/client/backend/types/aggregated_result.py +5 -7
  97. agenta/client/backend/types/aggregated_result_evaluator_config.py +1 -0
  98. agenta/client/backend/types/analytics_response.py +4 -6
  99. agenta/client/backend/types/annotation.py +50 -0
  100. agenta/client/backend/types/annotation_create.py +39 -0
  101. agenta/client/backend/types/annotation_edit.py +31 -0
  102. agenta/client/backend/types/annotation_kind.py +5 -0
  103. agenta/client/backend/types/{uri.py → annotation_link.py} +6 -7
  104. agenta/client/backend/types/{provider_key_dto.py → annotation_link_response.py} +6 -7
  105. agenta/client/backend/types/annotation_query.py +40 -0
  106. agenta/client/backend/types/annotation_query_request.py +20 -0
  107. agenta/client/backend/types/annotation_reference.py +21 -0
  108. agenta/client/backend/types/annotation_references.py +22 -0
  109. agenta/client/backend/types/{docker_env_vars.py → annotation_response.py} +6 -7
  110. agenta/client/backend/types/annotation_source.py +5 -0
  111. agenta/client/backend/types/annotations_response.py +24 -0
  112. agenta/client/backend/types/app.py +3 -5
  113. agenta/client/backend/types/app_variant_response.py +3 -6
  114. agenta/client/backend/types/app_variant_revision.py +5 -6
  115. agenta/client/backend/types/artifact.py +44 -0
  116. agenta/client/backend/types/base_output.py +3 -5
  117. agenta/client/backend/types/body_fetch_workflow_revision.py +21 -0
  118. agenta/client/backend/types/body_import_testset.py +3 -5
  119. agenta/client/backend/types/bucket_dto.py +4 -6
  120. agenta/client/backend/types/collect_status_response.py +3 -5
  121. agenta/client/backend/types/config_db.py +3 -5
  122. agenta/client/backend/types/config_dto.py +5 -7
  123. agenta/client/backend/types/config_response_model.py +5 -7
  124. agenta/client/backend/types/correct_answer.py +3 -5
  125. agenta/client/backend/types/create_app_output.py +3 -5
  126. agenta/client/backend/types/custom_model_settings_dto.py +3 -5
  127. agenta/client/backend/types/custom_provider_dto.py +6 -9
  128. agenta/client/backend/types/custom_provider_kind.py +5 -5
  129. agenta/client/backend/types/custom_provider_settings_dto.py +3 -5
  130. agenta/client/backend/types/data.py +2 -1
  131. agenta/client/backend/types/delete_evaluation.py +3 -5
  132. agenta/client/backend/types/environment_output.py +3 -5
  133. agenta/client/backend/types/environment_output_extended.py +4 -6
  134. agenta/client/backend/types/environment_revision.py +5 -5
  135. agenta/client/backend/types/error.py +3 -5
  136. agenta/client/backend/types/evaluation.py +6 -8
  137. agenta/client/backend/types/evaluation_scenario.py +5 -7
  138. agenta/client/backend/types/evaluation_scenario_input.py +3 -5
  139. agenta/client/backend/types/evaluation_scenario_output.py +4 -6
  140. agenta/client/backend/types/evaluation_scenario_result.py +4 -6
  141. agenta/client/backend/types/evaluator.py +31 -12
  142. agenta/client/backend/types/evaluator_config.py +3 -5
  143. agenta/client/backend/types/evaluator_flags.py +21 -0
  144. agenta/client/backend/types/evaluator_mapping_output_interface.py +3 -5
  145. agenta/client/backend/types/evaluator_output_interface.py +3 -5
  146. agenta/client/backend/types/evaluator_query.py +32 -0
  147. agenta/client/backend/types/evaluator_query_request.py +30 -0
  148. agenta/client/backend/types/evaluator_request.py +20 -0
  149. agenta/client/backend/types/evaluator_response.py +21 -0
  150. agenta/client/backend/types/evaluators_response.py +21 -0
  151. agenta/client/backend/types/exception_dto.py +3 -5
  152. agenta/client/backend/types/{o_tel_spans_response.py → extended_o_tel_tracing_response.py} +5 -7
  153. agenta/client/backend/types/focus.py +5 -0
  154. agenta/client/backend/types/format.py +5 -0
  155. agenta/client/backend/types/full_json_input.py +34 -0
  156. agenta/client/backend/types/full_json_output.py +29 -0
  157. agenta/client/backend/types/get_config_response.py +3 -5
  158. agenta/client/backend/types/{header_dto.py → header.py} +4 -6
  159. agenta/client/backend/types/http_validation_error.py +4 -6
  160. agenta/client/backend/types/human_evaluation.py +3 -5
  161. agenta/client/backend/types/human_evaluation_scenario.py +4 -6
  162. agenta/client/backend/types/human_evaluation_scenario_input.py +3 -5
  163. agenta/client/backend/types/human_evaluation_scenario_output.py +3 -5
  164. agenta/client/backend/types/invite_request.py +4 -6
  165. agenta/client/backend/types/legacy_analytics_response.py +4 -6
  166. agenta/client/backend/types/legacy_data_point.py +3 -5
  167. agenta/client/backend/types/legacy_evaluator.py +26 -0
  168. agenta/client/backend/types/legacy_scope_request.py +4 -6
  169. agenta/client/backend/types/legacy_scopes_response.py +3 -5
  170. agenta/client/backend/types/legacy_subscription_request.py +19 -0
  171. agenta/client/backend/types/legacy_user_request.py +5 -7
  172. agenta/client/backend/types/legacy_user_response.py +3 -5
  173. agenta/client/backend/types/lifecycle_dto.py +3 -5
  174. agenta/client/backend/types/link_dto.py +4 -6
  175. agenta/client/backend/types/list_api_keys_response.py +3 -5
  176. agenta/client/backend/types/llm_run_rate_limit.py +3 -5
  177. agenta/client/backend/types/meta_request.py +30 -0
  178. agenta/client/backend/types/metrics_dto.py +3 -5
  179. agenta/client/backend/types/new_testset.py +3 -5
  180. agenta/client/backend/types/node_dto.py +4 -6
  181. agenta/client/backend/types/o_tel_context_dto.py +3 -5
  182. agenta/client/backend/types/o_tel_event.py +35 -0
  183. agenta/client/backend/types/o_tel_event_dto.py +3 -5
  184. agenta/client/backend/types/o_tel_extra_dto.py +4 -6
  185. agenta/client/backend/types/o_tel_flat_span.py +56 -0
  186. agenta/client/backend/types/o_tel_flat_span_input_end_time.py +6 -0
  187. agenta/client/backend/types/o_tel_flat_span_input_start_time.py +6 -0
  188. agenta/client/backend/types/o_tel_flat_span_output_end_time.py +6 -0
  189. agenta/client/backend/types/o_tel_flat_span_output_start_time.py +6 -0
  190. agenta/client/backend/types/o_tel_link.py +34 -0
  191. agenta/client/backend/types/o_tel_link_dto.py +4 -6
  192. agenta/client/backend/types/o_tel_links_response.py +22 -0
  193. agenta/client/backend/types/o_tel_span.py +58 -0
  194. agenta/client/backend/types/o_tel_span_dto.py +8 -10
  195. agenta/client/backend/types/o_tel_span_input_end_time.py +6 -0
  196. agenta/client/backend/types/o_tel_span_input_spans_value.py +7 -0
  197. agenta/client/backend/types/o_tel_span_input_start_time.py +6 -0
  198. agenta/client/backend/types/o_tel_span_output_end_time.py +6 -0
  199. agenta/client/backend/types/o_tel_span_output_spans_value.py +30 -0
  200. agenta/client/backend/types/o_tel_span_output_start_time.py +6 -0
  201. agenta/client/backend/types/o_tel_spans_tree.py +22 -0
  202. agenta/client/backend/types/o_tel_spans_tree_input_spans_value.py +7 -0
  203. agenta/client/backend/types/o_tel_spans_tree_output_spans_value.py +5 -0
  204. agenta/client/backend/types/o_tel_status_code.py +1 -1
  205. agenta/client/backend/types/o_tel_tracing_data_response.py +22 -0
  206. agenta/client/backend/types/o_tel_tracing_request.py +22 -0
  207. agenta/client/backend/types/o_tel_tracing_response.py +27 -0
  208. agenta/client/backend/types/organization.py +3 -5
  209. agenta/client/backend/types/organization_details.py +3 -5
  210. agenta/client/backend/types/organization_membership_request.py +5 -7
  211. agenta/client/backend/types/organization_output.py +3 -5
  212. agenta/client/backend/types/organization_request.py +3 -5
  213. agenta/client/backend/types/parent_dto.py +3 -5
  214. agenta/client/backend/types/permission.py +11 -0
  215. agenta/client/backend/types/plan.py +14 -0
  216. agenta/client/backend/types/project_membership_request.py +5 -7
  217. agenta/client/backend/types/project_request.py +4 -6
  218. agenta/client/backend/types/project_scope.py +5 -7
  219. agenta/client/backend/types/projects_response.py +3 -5
  220. agenta/client/backend/types/recursive_types.py +23 -0
  221. agenta/client/backend/types/reference.py +18 -5
  222. agenta/client/backend/types/reference_dto.py +4 -5
  223. agenta/client/backend/types/reference_request_model.py +4 -5
  224. agenta/client/backend/types/result.py +4 -6
  225. agenta/client/backend/types/root_dto.py +3 -5
  226. agenta/client/backend/types/scopes_response_model.py +4 -6
  227. agenta/client/backend/types/secret_dto.py +5 -7
  228. agenta/client/backend/types/secret_response_dto.py +11 -11
  229. agenta/client/backend/types/simple_evaluation_output.py +4 -6
  230. agenta/client/backend/types/span_dto.py +18 -14
  231. agenta/client/backend/types/span_dto_nodes_value.py +1 -1
  232. agenta/client/backend/types/standard_provider_dto.py +5 -7
  233. agenta/client/backend/types/standard_provider_settings_dto.py +3 -5
  234. agenta/client/backend/types/status_dto.py +4 -6
  235. agenta/client/backend/types/tags_request.py +30 -0
  236. agenta/client/backend/types/test_set_output_response.py +5 -7
  237. agenta/client/backend/types/test_set_simple_response.py +3 -5
  238. agenta/client/backend/types/testcase_response.py +33 -0
  239. agenta/client/backend/types/testset.py +46 -0
  240. agenta/client/backend/types/testset_request.py +20 -0
  241. agenta/client/backend/types/testset_response.py +21 -0
  242. agenta/client/backend/types/testsets_response.py +21 -0
  243. agenta/client/backend/types/time_dto.py +3 -5
  244. agenta/client/backend/types/timestamp.py +6 -0
  245. agenta/client/backend/types/tree_dto.py +4 -6
  246. agenta/client/backend/types/update_app_output.py +3 -5
  247. agenta/client/backend/types/user_request.py +3 -5
  248. agenta/client/backend/types/validation_error.py +4 -6
  249. agenta/client/backend/types/workflow_artifact.py +45 -0
  250. agenta/client/backend/types/workflow_data.py +20 -0
  251. agenta/client/backend/types/workflow_flags.py +21 -0
  252. agenta/client/backend/types/workflow_request.py +20 -0
  253. agenta/client/backend/types/workflow_response.py +21 -0
  254. agenta/client/backend/types/workflow_revision.py +57 -0
  255. agenta/client/backend/types/workflow_revision_request.py +20 -0
  256. agenta/client/backend/types/workflow_revision_response.py +21 -0
  257. agenta/client/backend/types/workflow_revisions_response.py +21 -0
  258. agenta/client/backend/types/workflow_variant.py +48 -0
  259. agenta/client/backend/types/workflow_variant_request.py +20 -0
  260. agenta/client/backend/types/workflow_variant_response.py +21 -0
  261. agenta/client/backend/types/workflow_variants_response.py +21 -0
  262. agenta/client/backend/types/workflows_response.py +21 -0
  263. agenta/client/backend/types/workspace.py +3 -5
  264. agenta/client/backend/types/workspace_member_response.py +4 -6
  265. agenta/client/backend/types/workspace_membership_request.py +5 -7
  266. agenta/client/backend/types/workspace_permission.py +5 -7
  267. agenta/client/backend/types/workspace_request.py +4 -6
  268. agenta/client/backend/types/workspace_response.py +4 -6
  269. agenta/client/backend/variants/__init__.py +2 -0
  270. agenta/client/backend/variants/client.py +306 -1651
  271. agenta/client/backend/variants/raw_client.py +2482 -0
  272. agenta/client/backend/variants/types/__init__.py +2 -0
  273. agenta/client/backend/variants/types/add_variant_from_base_and_config_response.py +1 -0
  274. agenta/client/backend/vault/__init__.py +2 -0
  275. agenta/client/backend/vault/client.py +69 -323
  276. agenta/client/backend/vault/raw_client.py +616 -0
  277. agenta/client/backend/workflows/__init__.py +3 -0
  278. agenta/client/backend/workflows/client.py +2398 -0
  279. agenta/client/backend/workflows/raw_client.py +3639 -0
  280. agenta/client/backend/workspace/__init__.py +2 -0
  281. agenta/client/backend/workspace/client.py +46 -147
  282. agenta/client/backend/workspace/raw_client.py +376 -0
  283. agenta/client/types.py +4 -0
  284. agenta/sdk/types.py +28 -1
  285. {agenta-0.48.9.dist-info → agenta-0.48.10.dist-info}/METADATA +1 -1
  286. agenta-0.48.10.dist-info/RECORD +362 -0
  287. agenta/client/backend/containers/types/__init__.py +0 -5
  288. agenta/client/backend/containers/types/container_templates_response.py +0 -6
  289. agenta/client/backend/types/image.py +0 -25
  290. agenta/client/backend/types/provider_kind.py +0 -21
  291. agenta/client/backend/types/template.py +0 -23
  292. agenta/client/backend/types/template_image_info.py +0 -29
  293. agenta/client/backend/types/variant_action.py +0 -22
  294. agenta-0.48.9.dist-info/RECORD +0 -255
  295. {agenta-0.48.9.dist-info → agenta-0.48.10.dist-info}/WHEEL +0 -0
agenta/__init__.py CHANGED
@@ -2,6 +2,7 @@ from typing import Any, Callable, Optional
2
2
 
3
3
  from .sdk.utils.preinit import PreInitObject
4
4
 
5
+ from agenta.client import AgentaApi, AsyncAgentaApi
5
6
  import agenta.client.backend.types as client_types # pylint: disable=wrong-import-order
6
7
 
7
8
  from .sdk.types import (
@@ -42,8 +43,8 @@ DEFAULT_AGENTA_SINGLETON_INSTANCE = AgentaSingleton()
42
43
 
43
44
  types = client_types
44
45
 
45
- api = None
46
- async_api = None
46
+ api = AgentaApi
47
+ async_api = AsyncAgentaApi
47
48
 
48
49
  tracing = DEFAULT_AGENTA_SINGLETON_INSTANCE.tracing # type: ignore
49
50
  tracer = get_tracer(tracing)
agenta/client/Readme.md CHANGED
@@ -1,104 +1,282 @@
1
- Client code to communicate with the backend.
1
+ # Common Fern Issues with Pydantic Models
2
2
 
3
- Currently the models are manually copied from the backend code. This needs to change.
3
+ When using Fern to generate SDKs from FastAPI applications with Pydantic models, you may encounter several issues related to model naming conflicts, schema generation, and recursive type definitions. This document outlines the most common problems and their solutions.
4
4
 
5
- # Generate Backend
5
+ ## Issue 1: Model Name Conflicts
6
6
 
7
- To generate the client code using Fern, follow the steps below.
7
+ ### Problem Description
8
8
 
9
- 1. Open a Terminal and navigate to the folder where this Readme.md file is. For example;
10
- ```bash
11
- cd agenta/sdk/agenta/client
9
+ When you have multiple Pydantic models with the same name across different modules/folders and are used by different endpoints, Fern merges them into a single schema, causing field conflicts and unexpected behaviour.
10
+
11
+ **Example:**
12
+ ```python
13
+ # users/models.py
14
+ class User(BaseModel):
15
+ id: int
16
+ username: str
17
+ email: str
18
+
19
+ # admin_users/models.py
20
+ class User(BaseModel):
21
+ id: int
22
+ username: str
23
+ permissions: List[str]
24
+ is_admin: bool
12
25
  ```
13
26
 
14
- 2. Next ensure you have installed Fern by executing the command;
15
- ```bash
16
- npm install -g fern-api
27
+ Fern will merge these into one `User` schema, and when you run the `fern generate` command, it results in an error that involves conflicting field definitions.
28
+
29
+ ### Solutions
30
+
31
+ #### Solution 1: Use Unique Model Names
32
+
33
+ Rename your models to be more specific and avoid conflicts:
34
+
35
+ ```python
36
+ # users/models.py
37
+ class RegularUser(BaseModel):
38
+ id: int
39
+ username: str
40
+ email: str
41
+
42
+ # admin_users/models.py
43
+ class AdminUser(BaseModel):
44
+ id: int
45
+ username: str
46
+ permissions: List[str]
47
+ is_admin: bool
17
48
  ```
18
49
 
19
- 3. Execute this command to initialize Fern to import and use the OpenAPI spec;
20
-
21
- > To use an OpenAPI spec, you can pass in the filepath or URL.
22
- > We'll need to log in to use fern.
23
- > We'll be using a url to the openapi.json for [Agenta Cloud](https://cloud.agenta.ai).
24
- > Alternatively, for `cloud-dev` we could use [Cloud Local](http://localhost).
25
-
26
- ```bash
27
- fern init --openapi https://cloud.agenta.ai/api/openapi.json
28
- # fern init --openapi http://localhost/api/openapi.json
29
- ```
30
-
31
- 4. Add the Fern Python SDK;
32
- ```bash
33
- fern add fern-python-sdk
50
+ #### Solution 2: Use Pydantic's `model_config` with Custom Titles
51
+
52
+ Override the schema title to make models unique:
53
+
54
+ ```python
55
+ # users/models.py
56
+ class User(BaseModel):
57
+ model_config = ConfigDict(title="RegularUser")
58
+
59
+ id: int
60
+ username: str
61
+ email: str
62
+
63
+ # admin_users/models.py
64
+ class User(BaseModel):
65
+ model_config = ConfigDict(title="AdminUser")
66
+
67
+ id: int
68
+ username: str
69
+ permissions: List[str]
70
+ is_admin: bool
34
71
  ```
35
72
 
36
- 5. Go to the generators.yml, which would look like this;
37
- ```yaml
38
- default-group: local
39
- groups:
40
- local:
41
- generators:
42
- - name: fernapi/fern-typescript-node-sdk
43
- version: 0.9.5
44
- output:
45
- location: local-file-system
46
- path: ../sdks/typescript
47
- - name: fernapi/fern-python-sdk
48
- version: 0.6.0
73
+ #### Solution 3: Use Module-Prefixed Aliases
74
+
75
+ Create type aliases that include module context:
76
+
77
+ ```python
78
+ # users/models.py
79
+ class User(BaseModel):
80
+ id: int
81
+ username: str
82
+ email: str
83
+
84
+ # Create an alias for external use
85
+ UserModel = User
86
+
87
+ # admin_users/models.py
88
+ class User(BaseModel):
89
+ id: int
90
+ username: str
91
+ permissions: List[str]
92
+ is_admin: bool
93
+
94
+ # Create an alias for external use
95
+ AdminUserModel = User
49
96
  ```
50
97
 
51
- 6. Remove `fernapi/fern-typescript-node-sdk`;
52
- ```yaml
53
- default-group: local
54
- groups:
55
- local:
56
- generators:
57
- - name: fernapi/fern-python-sdk
58
- version: 3.10.6
98
+ Then use the aliases in your endpoints:
99
+
100
+ ```python
101
+ from users.models import UserModel
102
+ from admin_users.models import AdminUserModel
103
+
104
+ @app.get("/users/{user_id}", response_model=UserModel)
105
+ async def get_user(user_id: int):
106
+ # ...
107
+
108
+ @app.get("/admin/users/{user_id}", response_model=AdminUserModel)
109
+ async def get_admin_user(user_id: int):
110
+ # ...
59
111
  ```
60
112
 
61
- 7. Update `fernapi/fern-python-sdk`, which would look like this;
62
- ```yaml
63
- default-group: local
64
- groups:
65
- local:
66
- generators:
67
- - name: fernapi/fern-python-sdk
68
- version: 3.10.6
69
- output:
70
- location: local-file-system
71
- path: ./
113
+ ## Issue 2: Enum Schema Generation
114
+
115
+ ### Problem Description
116
+
117
+ When multiple Pydantic models reference the same Enum, Fern doesn't create a shared enum schema and instead inlines the enum values in each model, leading to code duplication and inconsistency.
118
+
119
+ **Example:**
120
+ ```python
121
+ class Status(Enum):
122
+ ACTIVE = "active"
123
+ INACTIVE = "inactive"
124
+ PENDING = "pending"
125
+
126
+ class User(BaseModel):
127
+ id: int
128
+ status: Status
129
+
130
+ class Order(BaseModel):
131
+ id: int
132
+ status: Status # Same enum, but Fern will not reuse the schema
72
133
  ```
73
- <img width="1001" alt="image" src="https://github.com/Agenta-AI/agenta/assets/56418363/f537691d-8dbb-4363-b7c0-ecef9f464053">
74
134
 
135
+ ### Solutions
75
136
 
76
- 8. Go to the fern.config.json file and change the value of "organization" to `agenta`
77
- <img width="593" alt="image" src="https://github.com/Agenta-AI/agenta/assets/56418363/0f44255e-50b5-4d78-863b-d33a3ec2eea0">
137
+ #### Solution 1: Explicit Schema Registration
78
138
 
79
-
80
- 9. Generate the client code
81
- ```bash
82
- fern generate
139
+ Force Pydantic to generate a proper schema reference by using the enum in a standalone model first:
140
+
141
+ ```python
142
+ from enum import Enum
143
+ from typing import Union
144
+ from pydantic import BaseModel
145
+
146
+ class Status(str, Enum):
147
+ ACTIVE = "active"
148
+ INACTIVE = "inactive"
149
+ PENDING = "pending"
150
+
151
+ # Create a dedicated schema model
152
+ class StatusSchema(BaseModel):
153
+ status: Status
154
+
155
+ class User(BaseModel):
156
+ id: int
157
+ status: Status
158
+
159
+ class Order(BaseModel):
160
+ id: int
161
+ status: Status
83
162
  ```
84
163
 
85
- 10. Go to `./containers/client.py`, search for the `build_image` function in the AgentaApi class and update `timeout_in_seconds` to `600` in `request_options'. It should now look like this;
164
+ #### Solution 2: Use Field with Schema Customization
165
+
166
+ Customize the field schema to ensure proper enum handling:
167
+
86
168
  ```python
87
- _response = self._client_wrapper.httpx_client.request(
88
- "containers/build_image",
89
- method="POST",
90
- params={
91
- "app_id": app_id,
92
- "base_name": base_name,
93
- },
94
- data={},
95
- files={
96
- "tar_file": tar_file,
97
- },
98
- request_options={**request_options, "timeout_in_seconds": 600},
99
- omit=OMIT,
169
+ from pydantic import BaseModel, Field
170
+ from enum import Enum
171
+
172
+ class Status(str, Enum):
173
+ ACTIVE = "active"
174
+ INACTIVE = "inactive"
175
+ PENDING = "pending"
176
+
177
+ class User(BaseModel):
178
+ id: int
179
+ status: Status = Field(
180
+ ...,
181
+ json_schema_extra={
182
+ "$ref": "#/components/schemas/Status"
183
+ }
184
+ )
185
+
186
+ class Order(BaseModel):
187
+ id: int
188
+ status: Status = Field(
189
+ ...,
190
+ json_schema_extra={
191
+ "$ref": "#/components/schemas/Status"
192
+ }
193
+ )
194
+ ```
195
+
196
+ ## Issue 3: Recursive Type Definitions
197
+
198
+ ### Problem Description
199
+
200
+ When using recursive type definitions with Pydantic v2 and Fern-generated SDKs, you may encounter infinite recursion during schema generation. This happens particularly with self-referential or mutually recursive types, such as JSON structures that can contain nested versions of themselves.
201
+
202
+ **Example of problematic recursive type definitions:**
203
+
204
+ ```python
205
+ from typing_extensions import TypeAliasType
206
+ from typing import Union, Dict, List
207
+
208
+ # This approach causes infinite recursion during schema generation
209
+ OTelJson: TypeAliasType = TypeAliasType(
210
+ "OTelJson",
211
+ Union[str, int, float, bool, None, Dict[str, "OTelJson"], List["OTelJson"]],
212
+ )
213
+
214
+ OTelNumericJson: TypeAliasType = TypeAliasType(
215
+ "OTelNumericJson",
216
+ Union[int, float, Dict[str, "OTelNumericJson"], List["OTelNumericJson"]],
100
217
  )
101
218
  ```
102
- <img width="995" alt="image" src="https://github.com/Agenta-AI/agenta/assets/56418363/8fab19e3-5226-405b-8a6f-4dcb6df588c9">
103
219
 
104
- 11. Delete the `./fern` folder.
220
+ Despite `TypeAliasType` being recommended in Pydantic v2 documentation for recursive types, it doesn't work well with Fern-generated models because:
221
+
222
+ 1. Fern's model generation may not properly handle these recursive references
223
+ 2. During schema generation, Pydantic attempts to expand these types infinitely
224
+ 3. Runtime errors occur during initialization or when creating JSON schemas
225
+
226
+ ### Solutions
227
+
228
+ #### Solution: Break Recursion with `Any` Type
229
+
230
+ Replace recursive self-references with `Any` for dictionary values and list items:
231
+
232
+ ```python
233
+ from typing import Any, Union, Dict, List
234
+
235
+ # Safe non-recursive version that prevents schema generation issues
236
+ OTelJson = Union[str, int, float, bool, None, Dict[str, Any], List[Any]]
237
+
238
+ # Using Any to break recursion cycle during schema generation
239
+ OTelNumericJson = Union[int, float, Dict[str, Any], List[Any]]
240
+ ```
241
+
242
+ #### Why This Works
243
+
244
+ 1. **Breaks the recursion cycle**: Using `Any` eliminates the self-reference that causes infinite recursion
245
+ 2. **Maintains functionality**: The types still functionally represent nested JSON structures
246
+ 3. **No schema generation issues**: Pydantic can generate schemas without infinite expansion
247
+ 4. **Simple implementation**: Requires no complex patches or runtime modifications
248
+
249
+ #### What to Avoid
250
+
251
+ 1. **Don't use complex monkey patching**: Patching Pydantic internals to handle recursion is fragile
252
+ 2. **Avoid disabling schema generation globally**: This impacts all models and API documentation
253
+ 3. **Don't use custom serialization for every model**: Introduces unnecessary complexity
254
+
255
+ When Fern generates your SDK, always check for recursive type definitions and convert them to use `Any` at appropriate recursion points to prevent these issues.
256
+
257
+
258
+ ## Troubleshooting
259
+
260
+ ### Debug Schema Generation
261
+
262
+ Add debugging to see what schemas are being generated:
263
+
264
+ ```python
265
+ import json
266
+ from your_app import app
267
+
268
+ # Generate and inspect OpenAPI schema
269
+ schema = app.openapi()
270
+ with open("debug_openapi.json", "w") as f:
271
+ json.dump(schema, f, indent=2)
272
+
273
+ # Check for duplicate schemas
274
+ schemas = schema.get("components", {}).get("schemas", {})
275
+ print("Generated schemas:", list(schemas.keys()))
276
+ ```
277
+
278
+ ### Common Error Patterns
279
+
280
+ 1. **"Schema conflict"** - Usually indicates duplicate model names
281
+ 2. **"Enum already exists"** - Enum not properly registered in other components/schemas
282
+ 3. **"Field type mismatch"** - Different models with same name have conflicting fields