astraform-sdk 0.3.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. astraform_sdk-0.3.5/PKG-INFO +698 -0
  2. astraform_sdk-0.3.5/README.md +667 -0
  3. astraform_sdk-0.3.5/pyproject.toml +73 -0
  4. astraform_sdk-0.3.5/setup.cfg +4 -0
  5. astraform_sdk-0.3.5/setup.py +37 -0
  6. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/__init__.py +63 -0
  7. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/_contract/contracts/remote-domain.v1.lock.json +9 -0
  8. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/_contract/contracts/remote-domain.v1.snapshot.json +80 -0
  9. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/_contract/resources.json +9 -0
  10. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/_contract/schemas/native-reference-state.schema.json +356 -0
  11. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/_contract/schemas/native-state-transform.schema.json +385 -0
  12. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/_contract/schemas/remote-domain.schema.json +902 -0
  13. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/fastapi.py +341 -0
  14. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/protocol.py +824 -0
  15. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/py.typed +1 -0
  16. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/templates/fastapi-minimal/README.md +150 -0
  17. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/templates/fastapi-minimal/pyproject.toml +34 -0
  18. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/templates/fastapi-minimal/scripts/bootstrap-local-sdk.sh +37 -0
  19. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/templates/fastapi-minimal/src/acme_remote_domain/__init__.py +1 -0
  20. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/templates/fastapi-minimal/src/acme_remote_domain/main.py +12 -0
  21. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/templates/fastapi-minimal/src/acme_remote_domain/population_catalog.json +69 -0
  22. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/templates/fastapi-minimal/src/acme_remote_domain/service.py +427 -0
  23. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/templates/fastapi-minimal/src/acme_remote_domain/validate_population_catalog.py +49 -0
  24. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/templates/fastapi-minimal/tests/test_app.py +180 -0
  25. astraform_sdk-0.3.5/src/astraform/remote_domain/author_kit/templates.py +90 -0
  26. astraform_sdk-0.3.5/src/astraform_platform_client/__init__.py +356 -0
  27. astraform_sdk-0.3.5/src/astraform_platform_client/api/__init__.py +12 -0
  28. astraform_sdk-0.3.5/src/astraform_platform_client/api/agent_catalog_api.py +2533 -0
  29. astraform_sdk-0.3.5/src/astraform_platform_client/api/agent_journeys_api.py +336 -0
  30. astraform_sdk-0.3.5/src/astraform_platform_client/api/domain_connections_api.py +3480 -0
  31. astraform_sdk-0.3.5/src/astraform_platform_client/api/evaluations_api.py +1721 -0
  32. astraform_sdk-0.3.5/src/astraform_platform_client/api/experiments_api.py +4365 -0
  33. astraform_sdk-0.3.5/src/astraform_platform_client/api/scenario_lab_api.py +2241 -0
  34. astraform_sdk-0.3.5/src/astraform_platform_client/api/simulation_events_api.py +2060 -0
  35. astraform_sdk-0.3.5/src/astraform_platform_client/api/simulation_runs_api.py +2965 -0
  36. astraform_sdk-0.3.5/src/astraform_platform_client/api_client.py +800 -0
  37. astraform_sdk-0.3.5/src/astraform_platform_client/api_response.py +21 -0
  38. astraform_sdk-0.3.5/src/astraform_platform_client/configuration.py +622 -0
  39. astraform_sdk-0.3.5/src/astraform_platform_client/contracts/platform-api.lock.json +10 -0
  40. astraform_sdk-0.3.5/src/astraform_platform_client/contracts/platform-api.snapshot.json +23 -0
  41. astraform_sdk-0.3.5/src/astraform_platform_client/exceptions.py +218 -0
  42. astraform_sdk-0.3.5/src/astraform_platform_client/models/__init__.py +163 -0
  43. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_invocation_evidence.py +233 -0
  44. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_invocation_receipt_evidence.py +179 -0
  45. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_invocation_request_evidence.py +120 -0
  46. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_normalized_application_request.py +112 -0
  47. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_normalized_receipt.py +187 -0
  48. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_normalized_receipt_not.py +155 -0
  49. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_normalized_receipt_one_of.py +138 -0
  50. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_normalized_receipt_one_of1.py +131 -0
  51. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_normalized_receipt_one_of2.py +131 -0
  52. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_normalized_receipt_one_of3.py +138 -0
  53. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_normalized_receipt_one_of4.py +128 -0
  54. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_normalized_receipt_one_of4_not.py +189 -0
  55. astraform_sdk-0.3.5/src/astraform_platform_client/models/a2a_stored_event_request.py +120 -0
  56. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_catalog_api_error.py +90 -0
  57. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_definition_create_request.py +116 -0
  58. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_definition_create_result.py +94 -0
  59. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_definition_default_revision_request.py +96 -0
  60. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_definition_draft.py +113 -0
  61. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_definition_draft_update_request.py +99 -0
  62. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_definition_publish_request.py +98 -0
  63. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_definition_publish_result.py +100 -0
  64. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_definition_revision_view.py +152 -0
  65. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_definition_view.py +160 -0
  66. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_domain_tool_grant.py +176 -0
  67. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_execution_binding.py +105 -0
  68. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_api_error.py +90 -0
  69. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_customer_reaction_facts.py +110 -0
  70. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_customer_reaction_observation.py +104 -0
  71. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_customer_reaction_progress.py +111 -0
  72. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_decision_schedule.py +95 -0
  73. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_domain_configuration.py +116 -0
  74. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_goal_completion_policy.py +146 -0
  75. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_goal_completion_policy_request_fact_bindings_inner.py +105 -0
  76. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_goal_condition.py +106 -0
  77. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_goal_condition_one_of_inner.py +160 -0
  78. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_goal_progress.py +133 -0
  79. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_goal_progress_achievement_evidence.py +112 -0
  80. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_goal_progress_rejected_request.py +93 -0
  81. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_launch_request.py +232 -0
  82. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_launch_response.py +160 -0
  83. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_native_progress.py +155 -0
  84. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_participation_progress.py +131 -0
  85. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_partner_exchange_payload.py +137 -0
  86. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_partner_exchange_payload_one_of.py +101 -0
  87. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_partner_exchange_payload_one_of1.py +105 -0
  88. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_partner_exchange_reference.py +104 -0
  89. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_scheduled_input.py +95 -0
  90. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_journey_tool_context.py +100 -0
  91. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_mcp_tool_grant.py +172 -0
  92. astraform_sdk-0.3.5/src/astraform_platform_client/models/agent_tool_grant.py +140 -0
  93. astraform_sdk-0.3.5/src/astraform_platform_client/models/artifact_register_request.py +94 -0
  94. astraform_sdk-0.3.5/src/astraform_platform_client/models/calibration_drift_summary.py +90 -0
  95. astraform_sdk-0.3.5/src/astraform_platform_client/models/calibration_observation_create_request.py +98 -0
  96. astraform_sdk-0.3.5/src/astraform_platform_client/models/calibration_observation_record.py +103 -0
  97. astraform_sdk-0.3.5/src/astraform_platform_client/models/compare_inline_request.py +106 -0
  98. astraform_sdk-0.3.5/src/astraform_platform_client/models/customer_mcp_binding.py +109 -0
  99. astraform_sdk-0.3.5/src/astraform_platform_client/models/customer_mcp_bindings.py +125 -0
  100. astraform_sdk-0.3.5/src/astraform_platform_client/models/customer_mcp_capabilities.py +130 -0
  101. astraform_sdk-0.3.5/src/astraform_platform_client/models/customer_mcp_tool_descriptor.py +147 -0
  102. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_assessment.py +179 -0
  103. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_assessment_dimension.py +113 -0
  104. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_assessment_dimension_delta.py +124 -0
  105. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_connection_api_error.py +93 -0
  106. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_connection_approve_request.py +101 -0
  107. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_connection_capabilities.py +100 -0
  108. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_connection_head.py +124 -0
  109. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_connection_list.py +116 -0
  110. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_connection_material.py +146 -0
  111. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_connection_mutation_request.py +92 -0
  112. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_connection_mutation_response.py +106 -0
  113. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_connection_probe.py +140 -0
  114. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_connection_registration_request.py +142 -0
  115. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_connection_revision.py +177 -0
  116. astraform_sdk-0.3.5/src/astraform_platform_client/models/domain_connection_revision_list.py +116 -0
  117. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluate_run_request.py +101 -0
  118. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_confidence.py +101 -0
  119. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_dimension.py +39 -0
  120. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_dimension_delta.py +98 -0
  121. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_dimension_score.py +106 -0
  122. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_evidence.py +95 -0
  123. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_run_metadata.py +125 -0
  124. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_run_report.py +128 -0
  125. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_run_summary.py +111 -0
  126. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_scenario_source.py +117 -0
  127. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_status.py +40 -0
  128. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_suite_result.py +140 -0
  129. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_summary.py +122 -0
  130. astraform_sdk-0.3.5/src/astraform_platform_client/models/evaluation_threshold_annotation.py +108 -0
  131. astraform_sdk-0.3.5/src/astraform_platform_client/models/event_input_evidence.py +154 -0
  132. astraform_sdk-0.3.5/src/astraform_platform_client/models/experiment_create_request.py +98 -0
  133. astraform_sdk-0.3.5/src/astraform_platform_client/models/experiment_record.py +103 -0
  134. astraform_sdk-0.3.5/src/astraform_platform_client/models/experiment_run_create_request.py +110 -0
  135. astraform_sdk-0.3.5/src/astraform_platform_client/models/experiment_run_record.py +119 -0
  136. astraform_sdk-0.3.5/src/astraform_platform_client/models/experiment_run_update_request.py +96 -0
  137. astraform_sdk-0.3.5/src/astraform_platform_client/models/native_domain_capabilities.py +147 -0
  138. astraform_sdk-0.3.5/src/astraform_platform_client/models/native_domain_profile.py +137 -0
  139. astraform_sdk-0.3.5/src/astraform_platform_client/models/native_domain_tool_descriptor.py +149 -0
  140. astraform_sdk-0.3.5/src/astraform_platform_client/models/native_pure_domain_profile.py +129 -0
  141. astraform_sdk-0.3.5/src/astraform_platform_client/models/native_reference_domain_profile.py +129 -0
  142. astraform_sdk-0.3.5/src/astraform_platform_client/models/public_simulation_input_request.py +97 -0
  143. astraform_sdk-0.3.5/src/astraform_platform_client/models/regression_delta_report.py +154 -0
  144. astraform_sdk-0.3.5/src/astraform_platform_client/models/regression_global_policy.py +95 -0
  145. astraform_sdk-0.3.5/src/astraform_platform_client/models/regression_policy.py +112 -0
  146. astraform_sdk-0.3.5/src/astraform_platform_client/models/regression_scenario_policy.py +91 -0
  147. astraform_sdk-0.3.5/src/astraform_platform_client/models/regression_threshold_breach.py +107 -0
  148. astraform_sdk-0.3.5/src/astraform_platform_client/models/resolved_domain_tool_grant.py +182 -0
  149. astraform_sdk-0.3.5/src/astraform_platform_client/models/resolved_mcp_tool_grant.py +190 -0
  150. astraform_sdk-0.3.5/src/astraform_platform_client/models/run_artifact_record.py +101 -0
  151. astraform_sdk-0.3.5/src/astraform_platform_client/models/run_evaluation_link_request.py +88 -0
  152. astraform_sdk-0.3.5/src/astraform_platform_client/models/scenario_evaluation_delta.py +134 -0
  153. astraform_sdk-0.3.5/src/astraform_platform_client/models/scenario_evaluation_result.py +151 -0
  154. astraform_sdk-0.3.5/src/astraform_platform_client/models/scenario_lab_api_error.py +107 -0
  155. astraform_sdk-0.3.5/src/astraform_platform_client/models/scenario_lab_bundle_payload.py +112 -0
  156. astraform_sdk-0.3.5/src/astraform_platform_client/models/scenario_lab_pack.py +116 -0
  157. astraform_sdk-0.3.5/src/astraform_platform_client/models/scenario_lab_pack_catalog.py +98 -0
  158. astraform_sdk-0.3.5/src/astraform_platform_client/models/scenario_lab_preset_catalog.py +107 -0
  159. astraform_sdk-0.3.5/src/astraform_platform_client/models/scenario_lab_run_control_request.py +112 -0
  160. astraform_sdk-0.3.5/src/astraform_platform_client/models/scenario_lab_run_start_request.py +105 -0
  161. astraform_sdk-0.3.5/src/astraform_platform_client/models/scenario_lab_run_status.py +138 -0
  162. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_agent_cursor.py +116 -0
  163. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_agent_cursor_state.py +38 -0
  164. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_agent_journey.py +117 -0
  165. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_event_launch_request.py +238 -0
  166. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_event_launch_request_all_of_domain_tool_grants.py +137 -0
  167. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_event_launch_request_all_of_tool_contexts.py +100 -0
  168. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_event_launch_response.py +98 -0
  169. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_event_state.py +39 -0
  170. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_event_status_response.py +163 -0
  171. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_journey_event.py +138 -0
  172. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_agent_batch_request.py +96 -0
  173. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_agent_record.py +107 -0
  174. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_batch_response.py +107 -0
  175. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_checkpoint.py +100 -0
  176. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_checkpoint_batch_request.py +96 -0
  177. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_checkpoint_record.py +107 -0
  178. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_create_request.py +108 -0
  179. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_event.py +112 -0
  180. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_event_all_of_payload.py +117 -0
  181. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_event_batch_request.py +96 -0
  182. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_ledger_response.py +126 -0
  183. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_list_response.py +145 -0
  184. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_record.py +133 -0
  185. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_record_metadata.py +105 -0
  186. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_update_request.py +114 -0
  187. astraform_sdk-0.3.5/src/astraform_platform_client/models/simulation_run_window.py +96 -0
  188. astraform_sdk-0.3.5/src/astraform_platform_client/models/source_snapshot_record.py +103 -0
  189. astraform_sdk-0.3.5/src/astraform_platform_client/models/source_snapshot_register_request.py +97 -0
  190. astraform_sdk-0.3.5/src/astraform_platform_client/py.typed +0 -0
  191. astraform_sdk-0.3.5/src/astraform_platform_client/rest.py +313 -0
  192. astraform_sdk-0.3.5/src/astraform_sdk.egg-info/PKG-INFO +698 -0
  193. astraform_sdk-0.3.5/src/astraform_sdk.egg-info/SOURCES.txt +200 -0
  194. astraform_sdk-0.3.5/src/astraform_sdk.egg-info/dependency_links.txt +1 -0
  195. astraform_sdk-0.3.5/src/astraform_sdk.egg-info/entry_points.txt +2 -0
  196. astraform_sdk-0.3.5/src/astraform_sdk.egg-info/requires.txt +17 -0
  197. astraform_sdk-0.3.5/src/astraform_sdk.egg-info/top_level.txt +2 -0
  198. astraform_sdk-0.3.5/tests/test_fastapi.py +611 -0
  199. astraform_sdk-0.3.5/tests/test_platform_domain_connections.py +205 -0
  200. astraform_sdk-0.3.5/tests/test_protocol.py +475 -0
  201. astraform_sdk-0.3.5/tests/test_security_boundaries.py +121 -0
  202. astraform_sdk-0.3.5/tests/test_templates.py +49 -0
@@ -0,0 +1,698 @@
1
+ Metadata-Version: 2.4
2
+ Name: astraform-sdk
3
+ Version: 0.3.5
4
+ Summary: Astraform SDK for Python: domain services, customer simulation and platform APIs
5
+ License-Expression: Apache-2.0
6
+ Project-URL: Documentation, https://astraform.ai/developers
7
+ Project-URL: Source, https://github.com/astraform/sdk-python
8
+ Project-URL: Publishing, https://github.com/astraform/sdk-python#readme
9
+ Keywords: astraform,domain-provider,simulation,conformance
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Framework :: FastAPI
13
+ Classifier: Typing :: Typed
14
+ Requires-Python: >=3.12
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: jsonschema<5.0,>=4.23
17
+ Requires-Dist: urllib3<3.0.0,>=2.6.3
18
+ Requires-Dist: python-dateutil>=2.8.2
19
+ Requires-Dist: pydantic<3.0.0,>=2.11
20
+ Requires-Dist: typing-extensions>=4.7.1
21
+ Provides-Extra: fastapi
22
+ Requires-Dist: fastapi<1.0,>=0.115; extra == "fastapi"
23
+ Requires-Dist: anyio<5.0,>=4.14.2; extra == "fastapi"
24
+ Requires-Dist: starlette<2.0,>=1.3.1; extra == "fastapi"
25
+ Provides-Extra: test
26
+ Requires-Dist: fastapi<1.0,>=0.115; extra == "test"
27
+ Requires-Dist: anyio<5.0,>=4.14.2; extra == "test"
28
+ Requires-Dist: starlette<2.0,>=1.3.1; extra == "test"
29
+ Requires-Dist: httpx<1.0,>=0.28; extra == "test"
30
+ Requires-Dist: pytest<10.0,>=9.0.3; extra == "test"
31
+
32
+ # Astraform SDK for Python
33
+
34
+ Version **0.3.5** is prepared as `astraform-sdk`, replacing the
35
+ `astraform-remote-domain-author-kit` distribution. It uses the checksum-pinned,
36
+ published **1.2.3** (`v1.2.3`) provider and platform contracts. The generated
37
+ client adds domain-connection operations and governed `REGISTERED` launch
38
+ selection alongside existing customer, simulation and evaluation operations.
39
+ Install this version after publication, or build from the checkout beforehand.
40
+
41
+ The SDK contains domain provider helpers for the `remote-domain.v1` protocol and
42
+ the generated platform client. Existing `astraform.remote_domain.author_kit` and
43
+ `astraform_platform_client` imports, public APIs and the
44
+ `astraform-remote-domain-copy-starter` command are unchanged. Conformance remains
45
+ separately installed provider validation tooling under `astraform-conformance`.
46
+
47
+ The package includes:
48
+
49
+ - reusable protocol constants and envelope builders
50
+ - request validation helpers
51
+ - an optional FastAPI app factory
52
+ - a starter template inside the package
53
+ - generated platform APIs under `astraform_platform_client`
54
+
55
+ ## Install
56
+
57
+ Use Python **3.12+**. Java and Maven are unnecessary for published wheels and
58
+ source archives, which include generated code and contract resources:
59
+
60
+ ```bash
61
+ python -m pip install 'astraform-sdk[fastapi]==0.3.5'
62
+ ```
63
+
64
+ When upgrading an existing environment from SDK 0.3.4 or older, update dependency
65
+ declarations and locks, then remove the old distribution before installing the
66
+ new name. They provide the same Python modules and must not be installed together:
67
+
68
+ ```bash
69
+ python -m pip uninstall astraform-remote-domain-author-kit
70
+ python -m pip install 'astraform-sdk[fastapi]==0.3.5'
71
+ ```
72
+
73
+ Published `astraform-remote-domain-author-kit==0.3.4` remains unchanged with its
74
+ 1.2.2 contracts. Version 0.3.5 uses 1.2.3; see the
75
+ [release notes](https://github.com/astraform/sdk-python/blob/main/docs/releases/0.3.5.md)
76
+ for compatibility requirements.
77
+
78
+ Omit `[fastapi]` if you only call Astraform. Conformance remains a separately
79
+ installed validation tool; no extra platform-client distribution is required.
80
+
81
+ Repository-local development requires Python 3.12+, Java 21 and Maven:
82
+
83
+ ```bash
84
+ pip install -e './sdk-python[fastapi,test]'
85
+ ```
86
+
87
+ The release workflow installs the exact built wheels into a clean environment,
88
+ copies the starter with `astraform-remote-domain-copy-starter`, installs that
89
+ project with `--no-deps`, validates its catalog, and runs the domain lifecycle
90
+ with population catalog plus Policy Wind Tunnel conformance. The same checks run
91
+ against published PyPI packages before creating the GitHub release. The separate
92
+ `scripts/bootstrap-local-sdk.sh` command is available for local development.
93
+
94
+ ## Platform API Client
95
+
96
+ The platform client is generated inside this package, not a second distribution.
97
+ The SDK wheel and source archive contain `astraform_platform_client`, its
98
+ runtime dependencies and snapshot provenance. Both install without Java/Maven.
99
+
100
+ ```python
101
+ from astraform_platform_client import ApiClient, Configuration
102
+ from astraform_platform_client.api.agent_catalog_api import AgentCatalogApi
103
+ from astraform_platform_client.api.agent_journeys_api import AgentJourneysApi
104
+ from astraform_platform_client.api.simulation_runs_api import SimulationRunsApi
105
+
106
+ client = ApiClient(Configuration(host="http://localhost:8484", retries=0))
107
+ catalog = AgentCatalogApi(client)
108
+ journeys = AgentJourneysApi(client)
109
+ runs = SimulationRunsApi(client)
110
+ ```
111
+
112
+ Use the Astraform API origin, without `/api` or `/api/dashboard`; generated
113
+ methods include canonical `/api/...` paths. The examples use a local gateway at
114
+ `http://localhost:8484`. Set the actual gateway origin for your deployment. Replaying a launch requires the same
115
+ request ID and unchanged request body. Do not add defaults to saved requests:
116
+ omission and explicit zero can have different identities.
117
+
118
+ The generated surface follows the Experiment OpenAPI specification. Dashboard
119
+ exposes Agent Catalog, Agent Journeys, Simulation Events/capability discovery and
120
+ Simulation Runs read, ledger, readiness and export operations. Other generated
121
+ Experiment/internal write operations require their own service endpoint; they
122
+ are not all exposed by Dashboard. An updated Dashboard must provide the canonical
123
+ aliases. Packaging does not change platform permissions or route exposure.
124
+
125
+ ### Create, publish, discover and launch
126
+
127
+ Start with the existing marketing
128
+ [`sample-configuration.json`](https://github.com/astraform/samples/blob/main/integration/marketing-ops-a2a/sample-configuration.json)
129
+ (requires repository access). Save it in your working directory. It supplies
130
+ `catalogDraftRequest` and `launchRequestTemplate`, including the human persona,
131
+ model binding, facts, domain scheduling and goal-evidence policy. Configure the
132
+ `local-customer` model, `marketing-ops` domain and `creative-agency` partner in the
133
+ deployment before running this example. The
134
+ [customer-simulation guide](https://github.com/astraform/platform/blob/dev/deploy/partner-evaluation/CUSTOMER-SIMULATION.md)
135
+ requires platform repository access and explains those bindings, persona/goals,
136
+ customer tools, partner-owned state and evidence. Package installation alone does
137
+ not configure them; obtain guide/sample access from your deployment owner.
138
+
139
+ This code uses the sample's exact request structure. It discovers the configured
140
+ domain, creates a customer definition, publishes its current draft and launches
141
+ that immutable revision. Use it once for a new run:
142
+
143
+ ```python
144
+ import json
145
+ from pathlib import Path
146
+ from uuid import uuid4
147
+
148
+ from astraform_platform_client import ApiClient, Configuration
149
+ from astraform_platform_client.api.agent_catalog_api import AgentCatalogApi
150
+ from astraform_platform_client.api.agent_journeys_api import AgentJourneysApi
151
+ from astraform_platform_client.api.simulation_events_api import SimulationEventsApi
152
+ from astraform_platform_client.models.agent_definition_create_request import AgentDefinitionCreateRequest
153
+ from astraform_platform_client.models.agent_definition_publish_request import AgentDefinitionPublishRequest
154
+ from astraform_platform_client.models.agent_journey_launch_request import AgentJourneyLaunchRequest
155
+
156
+ client = ApiClient(Configuration(host="http://localhost:8484", retries=0))
157
+ catalog = AgentCatalogApi(client)
158
+ sample = json.loads(Path("sample-configuration.json").read_text())
159
+ capabilities = SimulationEventsApi(client).inspect_public_native_domain_capabilities(
160
+ sample["launchRequestTemplate"]["domain"]["bindingKey"], _request_timeout=60.0)
161
+ print(capabilities.to_json())
162
+
163
+ draft = sample["catalogDraftRequest"]
164
+ draft["requestId"] = str(uuid4())
165
+ draft["agentKey"] = "marketing-customer-" + uuid4().hex[:12]
166
+ created = catalog.create_agent_definition(
167
+ AgentDefinitionCreateRequest.from_dict(draft), _request_timeout=60.0)
168
+ definition = created.definition
169
+ revision = catalog.publish_agent_definition(
170
+ definition.catalog_agent_id,
171
+ AgentDefinitionPublishRequest(
172
+ expected_draft_version=definition.draft_version,
173
+ expected_draft_spec_digest=definition.draft_spec_digest),
174
+ _request_timeout=60.0).revision
175
+
176
+ body = sample["launchRequestTemplate"]
177
+ body.update(requestId=str(uuid4()), catalogAgentId=str(definition.catalog_agent_id),
178
+ catalogRevisionId=str(revision.catalog_revision_id),
179
+ catalogDefinitionDigest=revision.catalog_definition_digest)
180
+ launch = AgentJourneyLaunchRequest.from_dict(body)
181
+ output = Path("run-" + str(launch.request_id))
182
+ output.mkdir()
183
+ (output / "launch-request.json").write_text(launch.to_json())
184
+ result = AgentJourneysApi(client).launch_agent_journey(launch, _request_timeout=60.0)
185
+ (output / "launch-response.json").write_text(result.to_json())
186
+ print("runId:", result.run_id, "saved to:", output)
187
+ ```
188
+
189
+ The platform owns subsequent customer decisions, partner exchanges and logical
190
+ time progression. This caller does not drive turns or advance a clock. If a
191
+ launch response is lost, reload the saved `launch-request.json` into
192
+ `AgentJourneyLaunchRequest` and resubmit that exact request, rather than rerunning
193
+ the code that creates new IDs. Preserve omitted optional fields and JSON scalar
194
+ types; do not fill in defaults during replay.
195
+
196
+ For the banking sample, use `inspect_public_customer_mcp_capabilities(binding_key)`
197
+ before publication and copy the returned binding/tool revision and digest pins
198
+ into the Catalog MCP grant, as its existing `run-customer.py` does. Its
199
+ `toolContexts` bind partner-owned `contextRef` and `subjectRef`; native domain
200
+ discovery alone does not grant customer access.
201
+
202
+ ### Inspect status and export evidence
203
+
204
+ Use the saved response for later reads. Substitute the directory printed above;
205
+ this step does not create or relaunch a customer:
206
+
207
+ ```python
208
+ import json
209
+ from pathlib import Path
210
+ from astraform_platform_client import ApiClient, Configuration
211
+ from astraform_platform_client.api.simulation_runs_api import SimulationRunsApi
212
+
213
+ output = Path("run-<saved-launch-request-id>")
214
+ run_id = json.loads((output / "launch-response.json").read_text())["runId"]
215
+ client = ApiClient(Configuration(host="http://localhost:8484", retries=0))
216
+ runs = SimulationRunsApi(client)
217
+ print(runs.get_simulation_run(run_id, _request_timeout=60.0).to_json())
218
+ print(runs.inspect_simulation_run_ledger(run_id, limit=100, _request_timeout=60.0).to_json())
219
+
220
+ # Once evidence is ready, this returns HTTP 204 with no body.
221
+ runs.get_simulation_run_evidence_export_readiness(run_id, _request_timeout=60.0)
222
+ (output / "evidence.zip").write_bytes(
223
+ runs.export_simulation_run_evidence(run_id, _request_timeout=60.0))
224
+ ```
225
+
226
+ Readiness/export can return `409` while evidence is unavailable and `404` for an
227
+ unknown run. Handle the SDK `ApiException` and retry the read when appropriate;
228
+ do not launch a replacement run. Inspect terminal status, ledger and goal
229
+ outcome together: successful transport or a valid customer response does not
230
+ mean the goal succeeded. Evaluate the recorded goal and assessment outcomes
231
+ separately from transport success.
232
+
233
+
234
+ ### Evaluate domain-owned results
235
+
236
+ The SDK generates `EvaluationsApi` in the same runtime distribution using the
237
+ published **1.2.3** contract, including domain-owned `domain_assessment.v1` fields.
238
+ These operations were introduced in contract **1.2.2** and SDK **0.3.4**; current
239
+ SDK **0.3.5** consumes 1.2.3. Use a matching platform deployment that supports
240
+ domain-owned assessments. SDK 0.3.3 does not include these evaluation operations.
241
+
242
+ Connect to the Experiment Service or a Dashboard exposing the canonical
243
+ `/api/evaluations` routes. Dashboard evaluation operations require the platform
244
+ administrator role. Use the API origin, without an `/api` suffix; SDK packaging
245
+ does not grant permissions or configure server routes.
246
+
247
+ Submit source evidence and assessments produced by your domain evaluator:
248
+
249
+ ```python
250
+ import json
251
+ from pathlib import Path
252
+ from astraform_platform_client import ApiClient, Configuration
253
+ from astraform_platform_client.api.evaluations_api import EvaluationsApi
254
+ from astraform_platform_client.models.evaluate_run_request import EvaluateRunRequest
255
+ from astraform_platform_client.models.compare_inline_request import CompareInlineRequest
256
+
257
+ suite = json.loads(Path("suite-result.json").read_text())
258
+ with ApiClient(Configuration(host="http://localhost:8484", retries=0)) as client:
259
+ evaluations = EvaluationsApi(client)
260
+ report = evaluations.evaluate(
261
+ EvaluateRunRequest(suiteResult=suite, persist=True), _request_timeout=60.0)
262
+ saved = evaluations.get_report(report.run.run_id)
263
+ summaries = evaluations.list_reports(run_id_like=report.run.run_id, limit=20)
264
+ policy = evaluations.get_policy()
265
+ stored_delta = evaluations.compare_stored_reports("baseline-run", report.run.run_id)
266
+ inline_delta = evaluations.compare_inline(
267
+ CompareInlineRequest(baselineReport=saved, candidateReport=report, policy=policy))
268
+ ```
269
+
270
+ The operation keeps `suiteResult` as a JSON object so unknown source evidence is
271
+ preserved. With the supporting contract, `DomainAssessment`,
272
+ `DomainAssessmentDimension`, `EvaluationSuiteResult` and
273
+ `EvaluationScenarioSource` provide typed construction and decoding. Their
274
+ `to_json()` methods produce JSON-safe values; `json.loads(model.to_json())` can be
275
+ used for the Map-shaped operation input. Preserve an already-assessed source as a
276
+ decoded dictionary, as above, or compute `evidenceDigest` after the final typed
277
+ source has been serialized. Typed date-time fields can normalize their spelling,
278
+ which changes the source snapshot used for the digest.
279
+
280
+ A domain assessment binds to its exact run, source digest and optional scenario.
281
+ Its digest uses RFC 8785 canonical JSON of the complete decoded suite after
282
+ removing the root `assessment` and each `scenarios[].assessment`. Preserve unknown
283
+ source fields when computing it. The SDK does not calculate scores, infer domain
284
+ rubrics or authenticate the evaluator's attribution. The server validates scope
285
+ and digest binding. A root assessment owns the aggregate; multiple scenario
286
+ scores are not automatically averaged. Source execution success remains separate
287
+ from assessment status.
288
+
289
+ Responses retain custom metrics, native domain results and optional/null values.
290
+ `NOT_ASSESSED` and `ERROR` do not imply a zero score. Check `comparisonStatus` and
291
+ `comparisonReason` before using a delta: historical and domain-owned reports, or
292
+ assessments with incompatible identities or score semantics, are not numerically
293
+ comparable. Historical `evaluation.v1` reports retain their original scores and
294
+ comparison behavior. Prefer SDK report responses over constructing report files
295
+ manually. `suiteResultPath` and `bundlePath`, when used, refer to paths available
296
+ to the service, rather than files on the SDK client's machine.
297
+
298
+
299
+ ### Build and contract provenance
300
+
301
+ Public API definitions are owned by
302
+ [`remote-domain-contracts`](https://github.com/astraform/remote-domain-contracts).
303
+ `contracts/platform-api.lock.json` pins the `platform-api` bundle version,
304
+ release asset and checksum. Setuptools resolves that dependency automatically
305
+ into ignored `.cache/platform-api/` and runs OpenAPI Generator 7.24.0 using
306
+ `pom.xml`. It generates the experiment/customer and evaluation API surface. No internal
307
+ agent-runtime API or sibling platform checkout is an input.
308
+
309
+ The shared **`v1.2.3` contract release is published**. Provider and platform
310
+ specifications use the same version and tag, with separate checksum-pinned archives.
311
+ Normal checkout builds use those released inputs. Published SDK 0.3.4 artifacts
312
+ retain 1.2.2; the 0.3.5 wheel below includes the checkout's 1.2.3 inputs:
313
+
314
+ ```bash
315
+ python -m build sdk-python --outdir dist/sdk
316
+ python -m pip install --force-reinstall dist/sdk/astraform_sdk-0.3.5-py3-none-any.whl
317
+ python -I scripts/smoke-platform-client.py
318
+ ```
319
+
320
+ The resolver verifies the pinned SHA on downloads and cached archives.
321
+ `ASTRAFORM_PLATFORM_API_OFFLINE=true` forbids downloads after the dependency has
322
+ been resolved once. To test unpublished contract changes, explicitly supply
323
+ `ASTRAFORM_CONTRACT_ZIP` and `ASTRAFORM_PLATFORM_API_ZIP`. Those inputs are kept
324
+ separately, marked `LOCAL_PRERELEASE`, and never selected implicitly by later
325
+ builds. CI and release require published inputs for both bundles.
326
+
327
+ Generated code is ignored under `src/astraform_platform_client/`. Wheel and
328
+ source archive include it and the generated `contracts/platform-api.snapshot.json`
329
+ plus release lock. Source archives build without Java, the contract repository
330
+ or a network connection once Python build requirements are installed. Missing
331
+ generated sources fail the build instead of producing a client-less SDK.
332
+
333
+ To update API definitions, change them in the contract repository, publish the
334
+ shared release, and update both SDK contract locks to the same version and tag.
335
+ No copied API tree is maintained in this SDK.
336
+
337
+ ## Core Usage
338
+
339
+ ```python
340
+ from astraform.remote_domain.author_kit.protocol import build_manifest
341
+ from astraform.remote_domain.author_kit.protocol import build_projection
342
+ from astraform.remote_domain.author_kit.protocol import opaque_state
343
+ from astraform.remote_domain.author_kit.protocol import projection_envelope
344
+ from astraform.remote_domain.author_kit.protocol import success_envelope
345
+ from astraform.remote_domain.author_kit.protocol import validate_request_envelope
346
+
347
+
348
+ def manifest() -> dict:
349
+ return build_manifest(
350
+ domain_id="acme-ops",
351
+ display_name="Acme Operations Domain",
352
+ description="Remote proof domain",
353
+ schema_version="acme-ops.state.v1",
354
+ supported_agent_types=["Operator"],
355
+ supported_interaction_modes=["SIMULATION", "HYBRID"],
356
+ tools=[
357
+ {
358
+ "name": "lookup_case",
359
+ "description": "Look up a case in the domain provider.",
360
+ "inputSchema": {"type": "object", "additionalProperties": False},
361
+ }
362
+ ],
363
+ )
364
+
365
+
366
+ def prepare(request: dict) -> dict:
367
+ validate_request_envelope(
368
+ request,
369
+ expected_domain_id="acme-ops",
370
+ expected_operation="prepare",
371
+ require_idempotency=True,
372
+ )
373
+ state = opaque_state(
374
+ "acme-ops.state.v1",
375
+ {"personaName": "Taylor", "completedWorkCount": 0},
376
+ )
377
+ projection = build_projection(
378
+ runtime_metadata={"domainProfile": "acme"},
379
+ status_view={"completedWorkCount": 0},
380
+ inspection_view={"tasks": []},
381
+ )
382
+ return success_envelope(
383
+ request,
384
+ runtime_identity="acme-ops::Taylor",
385
+ next_state=state,
386
+ projection=projection,
387
+ )
388
+
389
+
390
+ def status(request: dict) -> dict:
391
+ validate_request_envelope(
392
+ request,
393
+ expected_domain_id="acme-ops",
394
+ expected_operation="status",
395
+ require_state=True,
396
+ )
397
+ return projection_envelope(
398
+ request,
399
+ projection=build_projection(
400
+ runtime_metadata={"domainProfile": "acme"},
401
+ status_view={"completedWorkCount": 0},
402
+ inspection_view={"tasks": []},
403
+ ),
404
+ )
405
+ ```
406
+
407
+ Domain providers may add optional `evidence_events=[...]` to
408
+ `success_envelope(...)` or `projection_envelope(...)`. Use that lane for
409
+ provider-internal evidence that Astraform cannot observe directly, such as a
410
+ private third-party call or domain-owned policy check.
411
+
412
+ ## Native Event Simulation
413
+
414
+ Use the existing manifest builder; no provider-side manifest patching is needed:
415
+
416
+ ```python
417
+ manifest = build_manifest(
418
+ domain_id="acme-ops",
419
+ display_name="Acme Operations",
420
+ description="Provider-owned case reviews",
421
+ schema_version="acme.state.v1",
422
+ supports_domain_system_work_window=True,
423
+ native_simulation={
424
+ "profile": "remote-domain.native-state-transform.v1",
425
+ "providerRevision": "acme-build-42",
426
+ "mutationMode": "PURE_STATE_TRANSFORM",
427
+ "stateScope": "AGENT",
428
+ "workKinds": ["case_review"],
429
+ "maxWindowWorkItems": 1,
430
+ "initialBoundaryMode": "PREPARE_INCLUDES_START",
431
+ },
432
+ tools=[{
433
+ "name": "get_my_cases",
434
+ "description": "Read cases belonging to the configured customer.",
435
+ "revision": "v1",
436
+ "effectClass": "READ_ONLY",
437
+ "scope": "CUSTOMER_CONTEXT",
438
+ "inputSchema": {"type": "object", "additionalProperties": False},
439
+ "outputSchema": {
440
+ "type": "object",
441
+ "additionalProperties": False,
442
+ "properties": {"caseIds": {"type": "array", "items": {"type": "string"}}},
443
+ "required": ["caseIds"],
444
+ },
445
+ }],
446
+ )
447
+ ```
448
+
449
+ For partner-owned database state, select
450
+ `profile: remote-domain.native-reference-state.v1`,
451
+ `mutationMode: TRANSACTIONAL_REFERENCE_STATE`, and
452
+ `initialBoundaryMode: ATTACH_PREPOPULATED_STATE`. The remaining declaration
453
+ fields are shared. The provider remains responsible for its durable data,
454
+ scoped customer access, idempotency and the declared native execution semantics.
455
+
456
+ The builder validates native declarations against the embedded canonical schema.
457
+ A tool carrying `revision`, `effectClass` or `scope` must supply the complete
458
+ native read-only descriptor, including both schemas and its description.
459
+ Legacy name/description/inputSchema descriptors remain supported; declaring a
460
+ legacy tool does not make it eligible for native customer execution.
461
+ `extra_capabilities` accepts the same native declaration and receives the same
462
+ validation. Supply it there or through `native_simulation`, not both.
463
+
464
+ Existing envelope helpers carry provider metadata; they do not implement the
465
+ provider's event processing or advance Astraform's simulation. See the canonical
466
+ native profile definitions in the `remote-domain-contracts` release and the
467
+ conformance package's `validate_native` for metadata validation.
468
+
469
+ ## FastAPI App Factory
470
+
471
+ ```python
472
+ from astraform.remote_domain.author_kit.fastapi import create_fastapi_app
473
+
474
+ app = create_fastapi_app(
475
+ service=my_remote_domain_service,
476
+ policy_wind_tunnel_service=my_policy_wind_tunnel_service,
477
+ )
478
+ ```
479
+
480
+ Every POST route, including Policy Wind Tunnel routes, limits its incoming JSON
481
+ body to 4 MiB by default. The adapter counts actual streamed bytes before parsing
482
+ or calling the service, including requests without an accurate `Content-Length`.
483
+ Oversized bodies return HTTP 413 with `error.code=request_too_large`; malformed
484
+ UTF-8 JSON and non-object bodies return HTTP 400. Empty lifecycle-control bodies
485
+ remain supported. Set `create_fastapi_app(..., max_request_bytes=8 * 1024 * 1024)`
486
+ to use a different positive integer byte limit. This is an admission limit for
487
+ the complete request, separate from the manifest's `maxOpaqueStateBytes` setting.
488
+
489
+ ### Callback execution and capacity (0.2.1)
490
+
491
+ The factory dispatches all synchronous domain and Policy Wind Tunnel callbacks
492
+ through AnyIO worker threads. The HTTP request still waits for the actual result;
493
+ this does not introduce a background-job or accepted/pending API. Request context
494
+ variables are copied to the worker, and existing provider errors retain their
495
+ HTTP status and protocol envelope.
496
+
497
+ `max_concurrent_callbacks` is a positive integer, default **1**, shared by these
498
+ SDK callbacks within each app instance/process. This preserves serialized
499
+ provider calls while allowing health checks and unrelated async routes to run.
500
+ When every slot is occupied, another SDK callback receives HTTP **503** with
501
+ `error.code=provider_busy`, `category=transient_failure` and `retryable=true`.
502
+ It is not queued or invoked. Retry with backoff and the same idempotency key.
503
+ The health endpoint does not consume a slot; it reports liveness, not spare
504
+ callback capacity. Requests are still subject to the body limit above.
505
+
506
+ For a provider whose callbacks and database access support concurrent use:
507
+
508
+ ```python
509
+ app = create_fastapi_app(service=my_remote_domain_service, max_concurrent_callbacks=4)
510
+ ```
511
+
512
+ Choose this limit alongside the database connection pool and deployment worker
513
+ count. Uvicorn's `--workers` configures server processes in the partner deployment;
514
+ it is separate from this SDK limit. Each process has its own limit. Custom partner
515
+ routes and provider-created background jobs are outside the SDK callback limit.
516
+ Do not raise it without making shared state thread-safe. Even with the default of
517
+ one, successive calls can use different worker threads; use a connection pool or
518
+ create/use thread-affine resources inside the callback.
519
+
520
+ Once admitted, a callback may finish even if the caller cancels or disconnects.
521
+ Its slot stays occupied until the worker completes. Cancellation cannot undo a
522
+ database write or forcibly stop synchronous code. Providers must enforce their
523
+ own database/network timeouts and retain transactional idempotency/replay for
524
+ uncertain responses. Synchronous service methods remain the supported interface;
525
+ this change does not add an async provider interface or change simulated-time
526
+ acknowledgment and advancement rules.
527
+
528
+ The service object must implement:
529
+
530
+ - `manifest()`
531
+ - optional `population_catalog()` for
532
+ `GET /api/remote-domain/v1/population/catalog`
533
+ - `prepare(payload)`
534
+ - `execute_work(payload)`
535
+ - `status(payload)`
536
+ - `inspection(payload)`
537
+ - `shutdown(payload)`
538
+
539
+ `population_catalog()` must return `domain_population_catalog.v1`. The FastAPI
540
+ factory validates the catalog before returning it, so missing archetype fields,
541
+ bad recipe numbers, unknown archetype references, and malformed eligibility
542
+ fail before Population Builder treats the provider as usable.
543
+
544
+ Prefer a file-backed catalog over an inline Python dict. That keeps the domain
545
+ authoring surface reviewable and conformance-testable:
546
+
547
+ ```python
548
+ from importlib import resources
549
+
550
+ from astraform.remote_domain.author_kit import load_population_catalog
551
+
552
+
553
+ def population_catalog() -> dict:
554
+ catalog_file = resources.files("my_remote_domain").joinpath("population_catalog.json")
555
+ return load_population_catalog(catalog_file)
556
+ ```
557
+
558
+ `load_population_catalog(...)` reads JSON and runs the same
559
+ `validate_population_catalog(...)` checks used by the FastAPI route.
560
+
561
+ The bundled `fastapi-minimal` starter also installs a provider-local preflight:
562
+
563
+ ```bash
564
+ validate-population-catalog
565
+ ```
566
+
567
+ That command validates `src/acme_remote_domain/population_catalog.json` before
568
+ the provider starts and prints the exact rejected field when the catalog is
569
+ malformed. Treat it as the first command after editing archetypes, segment
570
+ templates, validation rules, or run-path eligibility.
571
+
572
+ The optional `policy_wind_tunnel_service` object exposes the remote Wind Tunnel
573
+ provider routes:
574
+
575
+ - `GET /policy-wind-tunnel/pack`
576
+ - `GET /policy-wind-tunnel/presets`
577
+ - `POST /policy-wind-tunnel/runs`
578
+ - `GET /policy-wind-tunnel/runs/{runId}`
579
+ - `POST /policy-wind-tunnel/runs/{runId}/lifecycle`
580
+ - `GET /policy-wind-tunnel/runs/{runId}/bundle`
581
+ - `GET /policy-wind-tunnel/runs/{runId}/artifacts/{artifactType}`
582
+ - `GET /policy-wind-tunnel/runs/{runId}/artifacts/{artifactType}/readiness`
583
+ - `GET /policy-wind-tunnel/runs/{runId}/evidence-pack`
584
+ - `GET /policy-wind-tunnel/runs/{runId}/evidence-pack/readiness`
585
+
586
+ The readiness routes are metadata-only checks for dashboard download UX. They
587
+ must prove the same provider-owned artifact/evidence-pack path is readable
588
+ without materializing the JSON body or ZIP archive.
589
+
590
+ ## Policy Expressions
591
+
592
+ When a domain exposes Policy Wind Tunnel behavior, CEL-compatible
593
+ `PolicyExpression` definitions are the portable decision contract. They are for
594
+ decision gates, eligibility checks, thresholds, and conformance-testable public
595
+ rules.
596
+
597
+ They are not the execution engine. Keep state mutation, external calls,
598
+ proprietary scoring, and side effects inside your service implementation or
599
+ domain-owned execution target. Use the expression's `executionTarget` as a
600
+ stable provider-owned target name.
601
+
602
+ Python providers should publish the same `/policy-wind-tunnel/pack` metadata as
603
+ Java providers. The helper below builds the portable parts of that response:
604
+
605
+ ```python
606
+ from astraform.remote_domain.author_kit import build_policy_expression
607
+ from astraform.remote_domain.author_kit import build_policy_wind_tunnel_pack_metadata
608
+
609
+
610
+ def wind_tunnel_pack() -> dict:
611
+ return build_policy_wind_tunnel_pack_metadata(
612
+ capabilities={"remoteProviderReady": True, "evidenceExport": True},
613
+ control_schema={
614
+ "type": "object",
615
+ "properties": {
616
+ "blockerCount": {"type": "integer", "minimum": 0},
617
+ },
618
+ },
619
+ ui_schema={
620
+ "fields": [
621
+ {"name": "blockerCount", "widget": "number", "label": "Blockers"},
622
+ ],
623
+ },
624
+ outcome_schema={
625
+ "schemaVersion": "domain_outcome_schema.v1",
626
+ "metricDefinitions": [
627
+ {
628
+ "metricId": "blockerCount",
629
+ "label": "Blockers",
630
+ "unit": "count",
631
+ "evidence": "domain-state",
632
+ },
633
+ ],
634
+ },
635
+ domain_labels={
636
+ "actorSingular": "campaign",
637
+ "actorPlural": "campaigns",
638
+ "simulatedActorsLabel": "Simulated campaigns",
639
+ },
640
+ policy_expressions=[
641
+ build_policy_expression(
642
+ expression_id="acme.blockers.acceptable",
643
+ expression="metrics.blockerCount <= 10",
644
+ execution_target="acme-policy-service",
645
+ description="Blockers must stay under launch threshold.",
646
+ ),
647
+ ],
648
+ )
649
+ ```
650
+
651
+ Keep policy expression contract shape in the public contract bundle and SDK
652
+ tests so Java and Python providers evaluate the same portable subset.
653
+
654
+ ## Starter Template
655
+
656
+ Copy the bundled FastAPI starter from the installed SDK:
657
+
658
+ ```bash
659
+ astraform-remote-domain-copy-starter acme-remote-domain
660
+ cd acme-remote-domain
661
+ pip install --no-deps -e .
662
+ validate-population-catalog
663
+ remote-domain-conformance --app acme_remote_domain.main:app --domain-id acme-remote --population-catalog
664
+ ```
665
+
666
+ The underlying template resource lives under:
667
+
668
+ - `astraform/remote_domain/author_kit/templates/fastapi-minimal`
669
+
670
+ It is intentionally boring. That is a feature. Teams need a truthful starting
671
+ point, not a framework demo that hides the protocol.
672
+
673
+ ## Publishing Status
674
+
675
+ Release validation starts with the standalone package tests:
676
+
677
+ ```bash
678
+ pytest sdk-python/tests conformance-python/tests
679
+ ```
680
+
681
+ PyPI artifacts are immutable. Do not rerun a publish for an already published
682
+ version; run smoke-only verification or bump the SDK version.
683
+
684
+ Public package note: PyPI distributions expose this SDK implementation. Keep
685
+ host runtime internals and domain-private logic out of this package.
686
+
687
+ ### Error diagnostics and downloaded files
688
+
689
+ Unexpected FastAPI failures return a generic protocol error. The response's
690
+ request ID identifies the complete exception in server logs; intentional
691
+ ProtocolError messages retain their public status and details.
692
+
693
+ The exported platform client's opt-in file response decoder writes through an
694
+ exclusively created temporary file in Configuration.temp_folder_path and
695
+ returns its unique random path. Content-Disposition does not choose the local
696
+ filename. Repeated downloads have independent paths; ordinary binary endpoint
697
+ wrappers continue returning bytes. Checkout builds and source distributions
698
+ retain this behavior through the existing generation step.