agent-learning-kit 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (642) hide show
  1. agent_learning_kit-0.1.0.dist-info/METADATA +381 -0
  2. agent_learning_kit-0.1.0.dist-info/RECORD +642 -0
  3. agent_learning_kit-0.1.0.dist-info/WHEEL +4 -0
  4. agent_learning_kit-0.1.0.dist-info/entry_points.txt +5 -0
  5. agent_learning_kit-0.1.0.dist-info/licenses/LICENSE +173 -0
  6. agent_learning_kit-0.1.0.dist-info/licenses/NOTICE +7 -0
  7. fi/__init__.py +5 -0
  8. fi/alk/__init__.py +57 -0
  9. fi/alk/_facade.py +31 -0
  10. fi/alk/_module_alias.py +68 -0
  11. fi/alk/_paths.py +14 -0
  12. fi/alk/_schema.py +522 -0
  13. fi/alk/actions.py +727 -0
  14. fi/alk/bench/__init__.py +517 -0
  15. fi/alk/bench/_codeexec.py +213 -0
  16. fi/alk/bench/_coding.py +215 -0
  17. fi/alk/bench/_docker.py +237 -0
  18. fi/alk/bench/_grader.py +286 -0
  19. fi/alk/bench/_pull.py +212 -0
  20. fi/alk/bench/_voice.py +147 -0
  21. fi/alk/capabilities.py +627 -0
  22. fi/alk/cli.py +6396 -0
  23. fi/alk/config.py +130 -0
  24. fi/alk/cua_loop.py +562 -0
  25. fi/alk/evals.py +2351 -0
  26. fi/alk/extensions.py +163 -0
  27. fi/alk/harness/ARCHITECTURE.md +231 -0
  28. fi/alk/harness/DESIGN.md +246 -0
  29. fi/alk/harness/ENVIRONMENT_CONFORMANCE.md +127 -0
  30. fi/alk/harness/HOW-IT-WORKS.md +297 -0
  31. fi/alk/harness/IMPLEMENTATION_AND_VALIDATION_STATUS.md +229 -0
  32. fi/alk/harness/README.md +417 -0
  33. fi/alk/harness/__init__.py +77 -0
  34. fi/alk/harness/__main__.py +3 -0
  35. fi/alk/harness/amend.py +312 -0
  36. fi/alk/harness/artifacts.py +319 -0
  37. fi/alk/harness/authoring_entrypoint.py +189 -0
  38. fi/alk/harness/authoring_runtime_validation.py +267 -0
  39. fi/alk/harness/backends/README.md +43 -0
  40. fi/alk/harness/backends/__init__.py +122 -0
  41. fi/alk/harness/backends/base.py +241 -0
  42. fi/alk/harness/backends/claude.py +211 -0
  43. fi/alk/harness/backends/files.py +182 -0
  44. fi/alk/harness/backends/vertex_gemini.py +457 -0
  45. fi/alk/harness/background_noise.py +95 -0
  46. fi/alk/harness/build.py +385 -0
  47. fi/alk/harness/bundle.py +593 -0
  48. fi/alk/harness/bundle_author_v2.py +1831 -0
  49. fi/alk/harness/bundle_v2.py +719 -0
  50. fi/alk/harness/call_runner.py +1440 -0
  51. fi/alk/harness/callback_http_adapter.py +111 -0
  52. fi/alk/harness/catalogue.py +287 -0
  53. fi/alk/harness/chat.py +428 -0
  54. fi/alk/harness/chat_call_runner.py +506 -0
  55. fi/alk/harness/checks.py +136 -0
  56. fi/alk/harness/cli.py +1354 -0
  57. fi/alk/harness/config.py +338 -0
  58. fi/alk/harness/contract.py +718 -0
  59. fi/alk/harness/credentials.py +674 -0
  60. fi/alk/harness/data/persona_vocabulary.json +111 -0
  61. fi/alk/harness/environment.py +99 -0
  62. fi/alk/harness/environment_plan.py +168 -0
  63. fi/alk/harness/events.py +125 -0
  64. fi/alk/harness/executor.py +304 -0
  65. fi/alk/harness/folder.py +234 -0
  66. fi/alk/harness/generated_runtime.py +815 -0
  67. fi/alk/harness/github.py +72 -0
  68. fi/alk/harness/hosted_authoring_entrypoint.py +183 -0
  69. fi/alk/harness/hosted_entrypoint.py +2402 -0
  70. fi/alk/harness/hosted_scheduler.py +2218 -0
  71. fi/alk/harness/job.py +426 -0
  72. fi/alk/harness/judge.py +184 -0
  73. fi/alk/harness/livekit_source.py +50 -0
  74. fi/alk/harness/livekit_tool_trace_bootstrap.py +71 -0
  75. fi/alk/harness/observability.py +208 -0
  76. fi/alk/harness/outbound.py +3252 -0
  77. fi/alk/harness/packaging.py +515 -0
  78. fi/alk/harness/persona_guides.py +157 -0
  79. fi/alk/harness/platform.py +692 -0
  80. fi/alk/harness/process_preflight.py +764 -0
  81. fi/alk/harness/process_runtime.py +5670 -0
  82. fi/alk/harness/prove.py +425 -0
  83. fi/alk/harness/provider_import.py +703 -0
  84. fi/alk/harness/provider_lifecycle.py +392 -0
  85. fi/alk/harness/provision.py +2896 -0
  86. fi/alk/harness/reception.py +147 -0
  87. fi/alk/harness/retell_chat_call_runner.py +373 -0
  88. fi/alk/harness/run/__init__.py +296 -0
  89. fi/alk/harness/run/alk.py +184 -0
  90. fi/alk/harness/run/call.py +162 -0
  91. fi/alk/harness/run/conversation.py +264 -0
  92. fi/alk/harness/run/data/voices_by_language_and_gender.json +693 -0
  93. fi/alk/harness/run/evidence.py +195 -0
  94. fi/alk/harness/run/grade.py +598 -0
  95. fi/alk/harness/run/live.py +297 -0
  96. fi/alk/harness/run/models.py +56 -0
  97. fi/alk/harness/run/platform_evals.py +227 -0
  98. fi/alk/harness/run/sdk_voice.py +130 -0
  99. fi/alk/harness/run/simulation.py +1209 -0
  100. fi/alk/harness/run/stage.py +91 -0
  101. fi/alk/harness/run/targets.py +508 -0
  102. fi/alk/harness/run/tools.py +601 -0
  103. fi/alk/harness/run/voice.py +340 -0
  104. fi/alk/harness/runtime.py +172 -0
  105. fi/alk/harness/sandbox_server.py +2011 -0
  106. fi/alk/harness/sandbox_worker.py +44 -0
  107. fi/alk/harness/scenario.py +1048 -0
  108. fi/alk/harness/scenario_source.py +879 -0
  109. fi/alk/harness/scenario_tools.py +1143 -0
  110. fi/alk/harness/scenarios.py +915 -0
  111. fi/alk/harness/secrets.py +168 -0
  112. fi/alk/harness/service_catalog.py +97 -0
  113. fi/alk/harness/session.py +391 -0
  114. fi/alk/harness/sessions.py +372 -0
  115. fi/alk/harness/simulator.py +76 -0
  116. fi/alk/harness/simulator_voice.py +928 -0
  117. fi/alk/harness/skills/build-environment/SKILL.md +538 -0
  118. fi/alk/harness/skills/harness.md +131 -0
  119. fi/alk/harness/skills/kinds/chat.md +48 -0
  120. fi/alk/harness/skills/kinds/voice-voicemail.md +63 -0
  121. fi/alk/harness/skills/kinds/voice.md +59 -0
  122. fi/alk/harness/skills/plan-suite/SKILL.md +103 -0
  123. fi/alk/harness/skills/provision-environment/SKILL.md +136 -0
  124. fi/alk/harness/skills/run-scenarios/SKILL.md +112 -0
  125. fi/alk/harness/skills/understand-agent/SKILL.md +251 -0
  126. fi/alk/harness/skills/write-scenarios/SKILL.md +606 -0
  127. fi/alk/harness/skills/write-scenarios/references/refusals.md +28 -0
  128. fi/alk/harness/skills/write-scenarios/references/world-api.md +92 -0
  129. fi/alk/harness/source_data_invariants.py +444 -0
  130. fi/alk/harness/source_tool_evidence.py +79 -0
  131. fi/alk/harness/sources.py +253 -0
  132. fi/alk/harness/spend.py +140 -0
  133. fi/alk/harness/tool_trace_proxy.py +104 -0
  134. fi/alk/harness/tools.py +1018 -0
  135. fi/alk/harness/understand.py +169 -0
  136. fi/alk/harness/voicemail_audio.py +74 -0
  137. fi/alk/harness/world/__init__.py +33 -0
  138. fi/alk/harness/world/errors.py +68 -0
  139. fi/alk/harness/world/expectations.py +91 -0
  140. fi/alk/harness/world/handle.py +538 -0
  141. fi/alk/harness/world/kinds.py +196 -0
  142. fi/alk/harness/world/mutate.py +186 -0
  143. fi/alk/harness/world/probe.py +413 -0
  144. fi/alk/harness/world/provision.py +511 -0
  145. fi/alk/harness/world/provisioned.py +191 -0
  146. fi/alk/harness/world/runtime.py +616 -0
  147. fi/alk/harness/world/snapshot.py +288 -0
  148. fi/alk/harness/world/stores/__init__.py +305 -0
  149. fi/alk/harness/world/stores/container.py +215 -0
  150. fi/alk/harness/world/stores/inprocess.py +346 -0
  151. fi/alk/harness/world/stores/postgres.py +481 -0
  152. fi/alk/harness/world/stores/prove.py +202 -0
  153. fi/alk/harness/world/stores/sqlite.py +245 -0
  154. fi/alk/harness/world/stores/written.py +182 -0
  155. fi/alk/harness/world/tools.py +1516 -0
  156. fi/alk/harness/world/workspace.py +144 -0
  157. fi/alk/image_loop.py +453 -0
  158. fi/alk/image_perturb.py +241 -0
  159. fi/alk/improve.py +274 -0
  160. fi/alk/live/__init__.py +154 -0
  161. fi/alk/live/_attribution.py +184 -0
  162. fi/alk/live/_capture.py +264 -0
  163. fi/alk/live/_codec.py +391 -0
  164. fi/alk/live/_contract.py +134 -0
  165. fi/alk/live/_loopback.py +316 -0
  166. fi/alk/live/_perturb.py +449 -0
  167. fi/alk/live/_runner.py +386 -0
  168. fi/alk/live/_stats.py +561 -0
  169. fi/alk/live/_transcript.py +240 -0
  170. fi/alk/live/_workers/__init__.py +9 -0
  171. fi/alk/live/_workers/a2a_worker.py +316 -0
  172. fi/alk/live/_workers/langgraph_worker.py +217 -0
  173. fi/alk/live/_workers/livekit_worker.py +207 -0
  174. fi/alk/live/_workers/mcp_loopback_server.py +46 -0
  175. fi/alk/live/_workers/mcp_worker.py +158 -0
  176. fi/alk/live/_workers/pipecat_worker.py +189 -0
  177. fi/alk/live/a2a_lane.py +138 -0
  178. fi/alk/live/langgraph_lane.py +339 -0
  179. fi/alk/live/livekit_lane.py +376 -0
  180. fi/alk/live/mcp_lane.py +172 -0
  181. fi/alk/live/pipecat_lane.py +341 -0
  182. fi/alk/live/voice_redteam.py +494 -0
  183. fi/alk/loss.py +306 -0
  184. fi/alk/optimize.py +36260 -0
  185. fi/alk/practice/__init__.py +51 -0
  186. fi/alk/practice/_assess.py +103 -0
  187. fi/alk/practice/_budget.py +81 -0
  188. fi/alk/practice/_calibrate.py +69 -0
  189. fi/alk/practice/_capstone.py +86 -0
  190. fi/alk/practice/_contract.py +91 -0
  191. fi/alk/practice/_diagnose.py +79 -0
  192. fi/alk/practice/_drill.py +196 -0
  193. fi/alk/practice/_experiment.py +720 -0
  194. fi/alk/practice/_schedule.py +102 -0
  195. fi/alk/practice/_store.py +194 -0
  196. fi/alk/practice/_trainer.py +245 -0
  197. fi/alk/practice/_update.py +125 -0
  198. fi/alk/redteam.py +2621 -0
  199. fi/alk/rewardhack.py +237 -0
  200. fi/alk/simulate.py +10351 -0
  201. fi/alk/studio/__init__.py +82 -0
  202. fi/alk/studio/_bias.py +314 -0
  203. fi/alk/studio/_calibration.py +522 -0
  204. fi/alk/studio/_coverage.py +262 -0
  205. fi/alk/studio/_download.py +665 -0
  206. fi/alk/studio/_fidelity_attack.py +114 -0
  207. fi/alk/studio/_generate.py +652 -0
  208. fi/alk/studio/_library.py +370 -0
  209. fi/alk/studio/_scan.py +134 -0
  210. fi/alk/studio/_upgrade.py +42 -0
  211. fi/alk/studio/_vendor.py +172 -0
  212. fi/alk/suite.py +4200 -0
  213. fi/alk/tasks.py +828 -0
  214. fi/alk/telemetry/__init__.py +149 -0
  215. fi/alk/telemetry/_contract.py +141 -0
  216. fi/alk/telemetry/_emit.py +182 -0
  217. fi/alk/telemetry/_ledger.py +296 -0
  218. fi/alk/telemetry/_queue.py +127 -0
  219. fi/alk/telemetry/_row.py +294 -0
  220. fi/alk/telemetry/_run.py +233 -0
  221. fi/alk/telemetry/_sync.py +193 -0
  222. fi/alk/telemetry/_url.py +119 -0
  223. fi/alk/trinity.py +49397 -0
  224. fi/alk/voice_loop.py +174 -0
  225. fi/api/__init__.py +1 -0
  226. fi/api/auth.py +137 -0
  227. fi/api/types.py +29 -0
  228. fi/cli/__init__.py +9 -0
  229. fi/cli/assertions/__init__.py +25 -0
  230. fi/cli/assertions/conditions.py +76 -0
  231. fi/cli/assertions/evaluator.py +286 -0
  232. fi/cli/assertions/exit_codes.py +20 -0
  233. fi/cli/assertions/parser.py +131 -0
  234. fi/cli/assertions/reporter.py +194 -0
  235. fi/cli/commands/__init__.py +9 -0
  236. fi/cli/commands/config.py +165 -0
  237. fi/cli/commands/export.py +208 -0
  238. fi/cli/commands/init.py +112 -0
  239. fi/cli/commands/list_cmd.py +213 -0
  240. fi/cli/commands/run.py +486 -0
  241. fi/cli/commands/validate.py +173 -0
  242. fi/cli/commands/view.py +424 -0
  243. fi/cli/config/__init__.py +6 -0
  244. fi/cli/config/defaults.py +206 -0
  245. fi/cli/config/loader.py +155 -0
  246. fi/cli/config/schema.py +174 -0
  247. fi/cli/main.py +78 -0
  248. fi/cli/output/__init__.py +6 -0
  249. fi/cli/output/formatters.py +106 -0
  250. fi/cli/output/reporters.py +46 -0
  251. fi/cli/storage/__init__.py +5 -0
  252. fi/cli/storage/run_history.py +249 -0
  253. fi/cli/utils/__init__.py +5 -0
  254. fi/cli/utils/console.py +44 -0
  255. fi/evals/__init__.py +131 -0
  256. fi/evals/autoeval/__init__.py +137 -0
  257. fi/evals/autoeval/analyzer.py +211 -0
  258. fi/evals/autoeval/config.py +244 -0
  259. fi/evals/autoeval/export.py +213 -0
  260. fi/evals/autoeval/interactive.py +283 -0
  261. fi/evals/autoeval/pipeline.py +625 -0
  262. fi/evals/autoeval/prompts.py +139 -0
  263. fi/evals/autoeval/recommender.py +242 -0
  264. fi/evals/autoeval/rules.py +589 -0
  265. fi/evals/autoeval/templates.py +299 -0
  266. fi/evals/autoeval/types.py +232 -0
  267. fi/evals/core/__init__.py +16 -0
  268. fi/evals/core/cloud_registry.py +184 -0
  269. fi/evals/core/engines.py +368 -0
  270. fi/evals/core/evaluate.py +319 -0
  271. fi/evals/core/judge_prompt.py +90 -0
  272. fi/evals/core/prompt_generator.py +83 -0
  273. fi/evals/core/registry.py +57 -0
  274. fi/evals/core/result.py +55 -0
  275. fi/evals/evaluator.py +721 -0
  276. fi/evals/execution.py +168 -0
  277. fi/evals/feedback/__init__.py +32 -0
  278. fi/evals/feedback/calibrator.py +160 -0
  279. fi/evals/feedback/collector.py +214 -0
  280. fi/evals/feedback/hooks.py +81 -0
  281. fi/evals/feedback/retriever.py +128 -0
  282. fi/evals/feedback/store.py +272 -0
  283. fi/evals/feedback/types.py +99 -0
  284. fi/evals/framework/README.md +79 -0
  285. fi/evals/framework/__init__.py +267 -0
  286. fi/evals/framework/backends/Dockerfile.eval-runner +33 -0
  287. fi/evals/framework/backends/__init__.py +99 -0
  288. fi/evals/framework/backends/_container.py +141 -0
  289. fi/evals/framework/backends/_utils.py +145 -0
  290. fi/evals/framework/backends/base.py +223 -0
  291. fi/evals/framework/backends/celery_backend.py +417 -0
  292. fi/evals/framework/backends/celery_worker.py +78 -0
  293. fi/evals/framework/backends/kubernetes_backend.py +665 -0
  294. fi/evals/framework/backends/ray_backend.py +521 -0
  295. fi/evals/framework/backends/temporal.py +350 -0
  296. fi/evals/framework/backends/temporal_worker.py +126 -0
  297. fi/evals/framework/backends/thread_pool.py +286 -0
  298. fi/evals/framework/context.py +258 -0
  299. fi/evals/framework/enrichment.py +306 -0
  300. fi/evals/framework/evals/__init__.py +68 -0
  301. fi/evals/framework/evals/agentic.py +399 -0
  302. fi/evals/framework/evals/builder.py +609 -0
  303. fi/evals/framework/evals/semantic.py +142 -0
  304. fi/evals/framework/evaluator.py +647 -0
  305. fi/evals/framework/evaluators/__init__.py +22 -0
  306. fi/evals/framework/evaluators/blocking.py +347 -0
  307. fi/evals/framework/evaluators/non_blocking.py +577 -0
  308. fi/evals/framework/propagation.py +421 -0
  309. fi/evals/framework/protocols.py +385 -0
  310. fi/evals/framework/registry.py +370 -0
  311. fi/evals/framework/resilience/__init__.py +150 -0
  312. fi/evals/framework/resilience/circuit_breaker.py +309 -0
  313. fi/evals/framework/resilience/degradation.py +355 -0
  314. fi/evals/framework/resilience/health.py +505 -0
  315. fi/evals/framework/resilience/rate_limiter.py +228 -0
  316. fi/evals/framework/resilience/retry.py +274 -0
  317. fi/evals/framework/resilience/types.py +288 -0
  318. fi/evals/framework/resilience/wrapper.py +433 -0
  319. fi/evals/framework/types.py +218 -0
  320. fi/evals/guardrails/README.md +915 -0
  321. fi/evals/guardrails/__init__.py +96 -0
  322. fi/evals/guardrails/backends/__init__.py +43 -0
  323. fi/evals/guardrails/backends/azure.py +361 -0
  324. fi/evals/guardrails/backends/base.py +88 -0
  325. fi/evals/guardrails/backends/generic_llm.py +163 -0
  326. fi/evals/guardrails/backends/granite.py +216 -0
  327. fi/evals/guardrails/backends/llamaguard.py +221 -0
  328. fi/evals/guardrails/backends/local_base.py +479 -0
  329. fi/evals/guardrails/backends/openai.py +365 -0
  330. fi/evals/guardrails/backends/qwen.py +170 -0
  331. fi/evals/guardrails/backends/shieldgemma.py +154 -0
  332. fi/evals/guardrails/backends/turing.py +235 -0
  333. fi/evals/guardrails/backends/vllm_client.py +321 -0
  334. fi/evals/guardrails/backends/wildguard.py +188 -0
  335. fi/evals/guardrails/base.py +888 -0
  336. fi/evals/guardrails/config.py +221 -0
  337. fi/evals/guardrails/discovery.py +243 -0
  338. fi/evals/guardrails/gateway.py +437 -0
  339. fi/evals/guardrails/registry.py +231 -0
  340. fi/evals/guardrails/scanners/__init__.py +127 -0
  341. fi/evals/guardrails/scanners/base.py +191 -0
  342. fi/evals/guardrails/scanners/code_injection.py +243 -0
  343. fi/evals/guardrails/scanners/eval_delegate.py +574 -0
  344. fi/evals/guardrails/scanners/invisible_chars.py +351 -0
  345. fi/evals/guardrails/scanners/jailbreak.py +412 -0
  346. fi/evals/guardrails/scanners/language.py +288 -0
  347. fi/evals/guardrails/scanners/pipeline.py +260 -0
  348. fi/evals/guardrails/scanners/regex.py +311 -0
  349. fi/evals/guardrails/scanners/secrets.py +274 -0
  350. fi/evals/guardrails/scanners/topics.py +649 -0
  351. fi/evals/guardrails/scanners/urls.py +341 -0
  352. fi/evals/guardrails/types.py +96 -0
  353. fi/evals/llm/__init__.py +3 -0
  354. fi/evals/llm/base_llm_provider.py +35 -0
  355. fi/evals/llm/providers/litellm.py +70 -0
  356. fi/evals/local/__init__.py +90 -0
  357. fi/evals/local/evaluator.py +690 -0
  358. fi/evals/local/execution_mode.py +121 -0
  359. fi/evals/local/llm.py +489 -0
  360. fi/evals/local/metrics/__init__.py +19 -0
  361. fi/evals/local/registry.py +360 -0
  362. fi/evals/manager.py +1018 -0
  363. fi/evals/manager_types.py +362 -0
  364. fi/evals/metrics/__init__.py +185 -0
  365. fi/evals/metrics/agents/__init__.py +74 -0
  366. fi/evals/metrics/agents/metrics.py +693 -0
  367. fi/evals/metrics/agents/report.py +36463 -0
  368. fi/evals/metrics/agents/types.py +160 -0
  369. fi/evals/metrics/base_llm_metric.py +111 -0
  370. fi/evals/metrics/base_metric.py +138 -0
  371. fi/evals/metrics/code_security/__init__.py +305 -0
  372. fi/evals/metrics/code_security/analyzer.py +985 -0
  373. fi/evals/metrics/code_security/benchmarks/__init__.py +73 -0
  374. fi/evals/metrics/code_security/benchmarks/builtin.py +750 -0
  375. fi/evals/metrics/code_security/benchmarks/loader.py +580 -0
  376. fi/evals/metrics/code_security/benchmarks/types.py +308 -0
  377. fi/evals/metrics/code_security/detectors/__init__.py +186 -0
  378. fi/evals/metrics/code_security/detectors/base.py +394 -0
  379. fi/evals/metrics/code_security/detectors/cryptography.py +345 -0
  380. fi/evals/metrics/code_security/detectors/injection.py +744 -0
  381. fi/evals/metrics/code_security/detectors/secrets.py +287 -0
  382. fi/evals/metrics/code_security/detectors/serialization.py +192 -0
  383. fi/evals/metrics/code_security/joint_metrics.py +588 -0
  384. fi/evals/metrics/code_security/judges/__init__.py +83 -0
  385. fi/evals/metrics/code_security/judges/base.py +238 -0
  386. fi/evals/metrics/code_security/judges/dual_judge.py +534 -0
  387. fi/evals/metrics/code_security/judges/llm_judge.py +301 -0
  388. fi/evals/metrics/code_security/judges/pattern_judge.py +515 -0
  389. fi/evals/metrics/code_security/metrics.py +388 -0
  390. fi/evals/metrics/code_security/modes/__init__.py +63 -0
  391. fi/evals/metrics/code_security/modes/adversarial.py +284 -0
  392. fi/evals/metrics/code_security/modes/autocomplete.py +198 -0
  393. fi/evals/metrics/code_security/modes/base.py +283 -0
  394. fi/evals/metrics/code_security/modes/instruct.py +253 -0
  395. fi/evals/metrics/code_security/modes/repair.py +230 -0
  396. fi/evals/metrics/code_security/reports/__init__.py +57 -0
  397. fi/evals/metrics/code_security/reports/generator.py +404 -0
  398. fi/evals/metrics/code_security/reports/leaderboard.py +509 -0
  399. fi/evals/metrics/code_security/types.py +534 -0
  400. fi/evals/metrics/function_calling/__init__.py +34 -0
  401. fi/evals/metrics/function_calling/metrics.py +573 -0
  402. fi/evals/metrics/function_calling/types.py +87 -0
  403. fi/evals/metrics/hallucination/__init__.py +54 -0
  404. fi/evals/metrics/hallucination/detector.py +149 -0
  405. fi/evals/metrics/hallucination/metrics.py +390 -0
  406. fi/evals/metrics/hallucination/nli.py +253 -0
  407. fi/evals/metrics/hallucination/sentinel.py +106 -0
  408. fi/evals/metrics/hallucination/types.py +132 -0
  409. fi/evals/metrics/heuristics/aggregation_metrics.py +85 -0
  410. fi/evals/metrics/heuristics/json_metrics.py +87 -0
  411. fi/evals/metrics/heuristics/similarity_metrics.py +375 -0
  412. fi/evals/metrics/heuristics/string_metrics.py +391 -0
  413. fi/evals/metrics/llm_as_judges/__init__.py +17 -0
  414. fi/evals/metrics/llm_as_judges/custom_judge/metric.py +112 -0
  415. fi/evals/metrics/llm_as_judges/custom_judge/prompts.py +26 -0
  416. fi/evals/metrics/llm_as_judges/types.py +48 -0
  417. fi/evals/metrics/rag/__init__.py +111 -0
  418. fi/evals/metrics/rag/advanced/__init__.py +14 -0
  419. fi/evals/metrics/rag/advanced/multi_hop.py +283 -0
  420. fi/evals/metrics/rag/advanced/source_attribution.py +344 -0
  421. fi/evals/metrics/rag/generation/__init__.py +17 -0
  422. fi/evals/metrics/rag/generation/answer_relevancy.py +176 -0
  423. fi/evals/metrics/rag/generation/context_utilization.py +245 -0
  424. fi/evals/metrics/rag/generation/faithfulness.py +241 -0
  425. fi/evals/metrics/rag/generation/groundedness.py +131 -0
  426. fi/evals/metrics/rag/rag_score.py +277 -0
  427. fi/evals/metrics/rag/retrieval/__init__.py +20 -0
  428. fi/evals/metrics/rag/retrieval/context_entity_recall.py +124 -0
  429. fi/evals/metrics/rag/retrieval/context_precision.py +158 -0
  430. fi/evals/metrics/rag/retrieval/context_recall.py +106 -0
  431. fi/evals/metrics/rag/retrieval/noise_sensitivity.py +163 -0
  432. fi/evals/metrics/rag/retrieval/ranking.py +261 -0
  433. fi/evals/metrics/rag/types.py +100 -0
  434. fi/evals/metrics/rag/utils/__init__.py +62 -0
  435. fi/evals/metrics/rag/utils/claims.py +189 -0
  436. fi/evals/metrics/rag/utils/entities.py +244 -0
  437. fi/evals/metrics/rag/utils/nli.py +92 -0
  438. fi/evals/metrics/rag/utils/similarity.py +345 -0
  439. fi/evals/metrics/structured/__init__.py +114 -0
  440. fi/evals/metrics/structured/field_completeness.py +313 -0
  441. fi/evals/metrics/structured/hierarchy_score.py +366 -0
  442. fi/evals/metrics/structured/json_validation.py +190 -0
  443. fi/evals/metrics/structured/schema_compliance.py +280 -0
  444. fi/evals/metrics/structured/structured_output_score.py +298 -0
  445. fi/evals/metrics/structured/types.py +108 -0
  446. fi/evals/metrics/structured/validators/__init__.py +30 -0
  447. fi/evals/metrics/structured/validators/base.py +189 -0
  448. fi/evals/metrics/structured/validators/json_validator.py +196 -0
  449. fi/evals/metrics/structured/validators/pydantic_validator.py +178 -0
  450. fi/evals/metrics/structured/validators/yaml_validator.py +248 -0
  451. fi/evals/otel/__init__.py +266 -0
  452. fi/evals/otel/config.py +400 -0
  453. fi/evals/otel/conventions.py +463 -0
  454. fi/evals/otel/enrichment.py +371 -0
  455. fi/evals/otel/instrumentors/__init__.py +140 -0
  456. fi/evals/otel/instrumentors/anthropic.py +517 -0
  457. fi/evals/otel/instrumentors/base.py +382 -0
  458. fi/evals/otel/instrumentors/openai.py +673 -0
  459. fi/evals/otel/processors/__init__.py +36 -0
  460. fi/evals/otel/processors/base.py +473 -0
  461. fi/evals/otel/processors/cost.py +445 -0
  462. fi/evals/otel/processors/evaluation.py +559 -0
  463. fi/evals/otel/processors/llm.py +462 -0
  464. fi/evals/otel/tracer.py +506 -0
  465. fi/evals/otel/types.py +232 -0
  466. fi/evals/otel_utils.py +23 -0
  467. fi/evals/protect.py +671 -0
  468. fi/evals/protect_input_adapter.py +154 -0
  469. fi/evals/streaming/__init__.py +88 -0
  470. fi/evals/streaming/buffer.py +213 -0
  471. fi/evals/streaming/evaluator.py +551 -0
  472. fi/evals/streaming/policy.py +307 -0
  473. fi/evals/streaming/scorers.py +368 -0
  474. fi/evals/streaming/types.py +238 -0
  475. fi/evals/templates.py +472 -0
  476. fi/evals/types.py +156 -0
  477. fi/opt/__init__.py +221 -0
  478. fi/opt/_objective_scoring.py +85 -0
  479. fi/opt/base/__init__.py +11 -0
  480. fi/opt/base/base_generator.py +33 -0
  481. fi/opt/base/base_mapper.py +26 -0
  482. fi/opt/base/base_optimizer.py +45 -0
  483. fi/opt/base/evaluator.py +211 -0
  484. fi/opt/components.py +3095 -0
  485. fi/opt/datamappers/__init__.py +3 -0
  486. fi/opt/datamappers/basic_mapper.py +40 -0
  487. fi/opt/deployment.py +1021 -0
  488. fi/opt/evidence.py +4332 -0
  489. fi/opt/generators/__init__.py +3 -0
  490. fi/opt/generators/litellm.py +66 -0
  491. fi/opt/integrations/__init__.py +23 -0
  492. fi/opt/integrations/generative_suite.py +410 -0
  493. fi/opt/integrations/simulate.py +1313 -0
  494. fi/opt/mutations.py +771 -0
  495. fi/opt/observability.py +4639 -0
  496. fi/opt/optimizer_trace.py +889 -0
  497. fi/opt/optimizers/__init__.py +80 -0
  498. fi/opt/optimizers/agent.py +331 -0
  499. fi/opt/optimizers/agent_bandit.py +392 -0
  500. fi/opt/optimizers/agent_curriculum.py +635 -0
  501. fi/opt/optimizers/agent_evolution.py +894 -0
  502. fi/opt/optimizers/agent_feedback.py +1863 -0
  503. fi/opt/optimizers/agent_pareto.py +547 -0
  504. fi/opt/optimizers/agent_social_memory.py +1113 -0
  505. fi/opt/optimizers/agent_tpe.py +321 -0
  506. fi/opt/optimizers/bayesian_search.py +449 -0
  507. fi/opt/optimizers/council.py +2075 -0
  508. fi/opt/optimizers/futureagi_replay.py +799 -0
  509. fi/opt/optimizers/gepa.py +322 -0
  510. fi/opt/optimizers/metaprompt.py +243 -0
  511. fi/opt/optimizers/promptwizard.py +417 -0
  512. fi/opt/optimizers/protegi.py +329 -0
  513. fi/opt/optimizers/random_search.py +224 -0
  514. fi/opt/research.py +518 -0
  515. fi/opt/simulation.py +260 -0
  516. fi/opt/targets.py +232 -0
  517. fi/opt/types.py +66 -0
  518. fi/opt/utils/__init__.py +4 -0
  519. fi/opt/utils/early_stopping.py +266 -0
  520. fi/opt/utils/setup_logging.py +82 -0
  521. fi/simulate/__init__.py +540 -0
  522. fi/simulate/_hashing.py +35 -0
  523. fi/simulate/_logging.py +10 -0
  524. fi/simulate/adapters.py +87 -0
  525. fi/simulate/agent/__init__.py +120 -0
  526. fi/simulate/agent/browser.py +658 -0
  527. fi/simulate/agent/definition.py +587 -0
  528. fi/simulate/agent/frameworks.py +3528 -0
  529. fi/simulate/agent/generic.py +8286 -0
  530. fi/simulate/agent/import_probe.py +227 -0
  531. fi/simulate/agent/memory.py +905 -0
  532. fi/simulate/agent/mocks.py +101 -0
  533. fi/simulate/agent/multi_agent.py +361 -0
  534. fi/simulate/agent/orchestration.py +903 -0
  535. fi/simulate/agent/realtime.py +665 -0
  536. fi/simulate/agent/wrapper.py +99 -0
  537. fi/simulate/agent/wrappers/__init__.py +18 -0
  538. fi/simulate/agent/wrappers/anthropic.py +62 -0
  539. fi/simulate/agent/wrappers/gemini.py +65 -0
  540. fi/simulate/agent/wrappers/http.py +404 -0
  541. fi/simulate/agent/wrappers/langchain.py +80 -0
  542. fi/simulate/agent/wrappers/openai.py +75 -0
  543. fi/simulate/agent/wrappers/websocket.py +326 -0
  544. fi/simulate/artifacts/__init__.py +11 -0
  545. fi/simulate/artifacts/manifest.py +62 -0
  546. fi/simulate/cli.py +20560 -0
  547. fi/simulate/endpoints/__init__.py +45 -0
  548. fi/simulate/endpoints/_http_actor.py +73 -0
  549. fi/simulate/endpoints/actor_sources.py +243 -0
  550. fi/simulate/endpoints/base.py +107 -0
  551. fi/simulate/endpoints/builtins.py +10 -0
  552. fi/simulate/endpoints/callable.py +95 -0
  553. fi/simulate/endpoints/http.py +76 -0
  554. fi/simulate/endpoints/livekit.py +138 -0
  555. fi/simulate/endpoints/originators.py +132 -0
  556. fi/simulate/endpoints/profiles.py +348 -0
  557. fi/simulate/endpoints/retell.py +633 -0
  558. fi/simulate/endpoints/vapi.py +205 -0
  559. fi/simulate/endpoints/websocket.py +76 -0
  560. fi/simulate/environment.py +33026 -0
  561. fi/simulate/environments/__init__.py +11 -0
  562. fi/simulate/environments/base.py +73 -0
  563. fi/simulate/environments/chat.py +697 -0
  564. fi/simulate/environments/voice.py +212 -0
  565. fi/simulate/evaluation/__init__.py +4 -0
  566. fi/simulate/evaluation/ai_eval.py +227 -0
  567. fi/simulate/evidence/__init__.py +35 -0
  568. fi/simulate/evidence/base.py +59 -0
  569. fi/simulate/evidence/caller_observed.py +50 -0
  570. fi/simulate/evidence/livekit_instrumentation.py +51 -0
  571. fi/simulate/evidence/livekit_room.py +50 -0
  572. fi/simulate/evidence/otel.py +49 -0
  573. fi/simulate/evidence/providers/__init__.py +24 -0
  574. fi/simulate/evidence/providers/base.py +61 -0
  575. fi/simulate/evidence/providers/retell.py +376 -0
  576. fi/simulate/evidence/providers/vapi.py +426 -0
  577. fi/simulate/hosted/__init__.py +32 -0
  578. fi/simulate/hosted/child_entrypoint.py +306 -0
  579. fi/simulate/hosted/job.py +150 -0
  580. fi/simulate/hosted/targets.py +53 -0
  581. fi/simulate/instrumentation/__init__.py +5 -0
  582. fi/simulate/instrumentation/livekit/__init__.py +122 -0
  583. fi/simulate/manifest.py +1033 -0
  584. fi/simulate/matrix_cli.py +165 -0
  585. fi/simulate/realtime/__init__.py +40 -0
  586. fi/simulate/realtime/events.py +107 -0
  587. fi/simulate/realtime/media.py +61 -0
  588. fi/simulate/realtime/session.py +91 -0
  589. fi/simulate/recording/__init__.py +5 -0
  590. fi/simulate/recording/room_recorder.py +326 -0
  591. fi/simulate/registry.py +185 -0
  592. fi/simulate/results/__init__.py +9 -0
  593. fi/simulate/results/base.py +18 -0
  594. fi/simulate/results/filesystem.py +71 -0
  595. fi/simulate/results/futureagi.py +1340 -0
  596. fi/simulate/runtime/__init__.py +85 -0
  597. fi/simulate/runtime/capabilities.py +40 -0
  598. fi/simulate/runtime/events.py +63 -0
  599. fi/simulate/runtime/failures.py +25 -0
  600. fi/simulate/runtime/ids.py +34 -0
  601. fi/simulate/runtime/plan.py +70 -0
  602. fi/simulate/runtime/planner.py +102 -0
  603. fi/simulate/runtime/report.py +174 -0
  604. fi/simulate/runtime/run.py +75 -0
  605. fi/simulate/runtime/runner.py +333 -0
  606. fi/simulate/runtime/spec.py +186 -0
  607. fi/simulate/simulation/__init__.py +30 -0
  608. fi/simulate/simulation/behavior_policy.py +425 -0
  609. fi/simulate/simulation/bridge/__init__.py +9 -0
  610. fi/simulate/simulation/bridge/audio.py +29 -0
  611. fi/simulate/simulation/bridge/connector.py +46 -0
  612. fi/simulate/simulation/bridge/livekit.py +252 -0
  613. fi/simulate/simulation/bridge/retell.py +188 -0
  614. fi/simulate/simulation/bridge/vapi.py +177 -0
  615. fi/simulate/simulation/contract.py +419 -0
  616. fi/simulate/simulation/engines/__init__.py +12 -0
  617. fi/simulate/simulation/engines/base.py +21 -0
  618. fi/simulate/simulation/engines/cloud.py +517 -0
  619. fi/simulate/simulation/engines/livekit.py +4167 -0
  620. fi/simulate/simulation/engines/local_text.py +89 -0
  621. fi/simulate/simulation/fidelity.py +374 -0
  622. fi/simulate/simulation/gemini_tts_stream.py +110 -0
  623. fi/simulate/simulation/generator.py +91 -0
  624. fi/simulate/simulation/goal_machine.py +185 -0
  625. fi/simulate/simulation/livekit_models.py +467 -0
  626. fi/simulate/simulation/matrix.py +170 -0
  627. fi/simulate/simulation/models.py +279 -0
  628. fi/simulate/simulation/runner.py +153 -0
  629. fi/simulate/simulation/synthetic.py +880 -0
  630. fi/simulate/simulation/voice_prompt.py +502 -0
  631. fi/simulate/simulator/__init__.py +55 -0
  632. fi/simulate/simulator/builtins.py +53 -0
  633. fi/simulate/suite.py +1288 -0
  634. fi/simulate/utils/routes.py +164 -0
  635. fi/simulate/voice.py +225 -0
  636. fi/simulate/voice_cli.py +182 -0
  637. fi/utils/__init__.py +1 -0
  638. fi/utils/constants.py +14 -0
  639. fi/utils/errors.py +200 -0
  640. fi/utils/executor.py +26 -0
  641. fi/utils/routes.py +119 -0
  642. fi/utils/utils.py +17 -0
@@ -0,0 +1,799 @@
1
+ from __future__ import annotations
2
+
3
+ import copy
4
+ import json
5
+ from typing import Any, Callable, Mapping, Optional, Sequence
6
+
7
+ from pydantic import BaseModel, Field
8
+
9
+ from ..base.base_optimizer import BaseOptimizer
10
+ from ..deployment import AgentDeploymentExport, export_agent_deployment
11
+ from ..observability import (
12
+ AgentRegressionDataset,
13
+ AgentObservabilityWindow,
14
+ AgentRegistryReplayPackLineageReport,
15
+ AgentRegistryReplayPackTriageReport,
16
+ load_futureagi_experiment_history,
17
+ load_futureagi_regression_dataset,
18
+ )
19
+ from ..targets import AgentCandidate, CandidateEvaluation, OptimizationTarget
20
+ from ..types import EvaluationResult
21
+ from .agent_feedback import (
22
+ AgentFeedbackOptimizationResult,
23
+ AgentFeedbackOptimizer,
24
+ AgentMultiInteractionOptimizationResult,
25
+ AgentMultiInteractionOptimizer,
26
+ DEFAULT_MULTI_INTERACTION_BACKENDS,
27
+ _normalize_optimizer_name,
28
+ )
29
+
30
+
31
+ CandidateScorer = Callable[
32
+ [AgentCandidate],
33
+ CandidateEvaluation | EvaluationResult | float,
34
+ ]
35
+ FUTUREAGI_REPLAY_OPTIMIZER_SCHEDULE_SCHEMA_VERSION = (
36
+ "agent-opt.futureagi-replay-optimizer-schedule.v1"
37
+ )
38
+ _REPLAY_EVIDENCE_BLOCKERS = {
39
+ "futureagi_readback_signature_mismatch",
40
+ "futureagi_readback_case_count_mismatch",
41
+ "futureagi_replay_record_count_mismatch",
42
+ "latest_promotion_failed",
43
+ "latest_promotion_failures",
44
+ "missing_latest_promotion_check",
45
+ "missing_latest_optimizer_score",
46
+ }
47
+ _REPLAY_PORTFOLIO_TRIGGERS = {
48
+ "optimizer_score_regression",
49
+ "latest_below_best_optimizer_score",
50
+ "selected_patch_changed",
51
+ "optimizer_backend_changed",
52
+ "case_signature_changed",
53
+ }
54
+ _REPLAY_CURRICULUM_TRIGGERS = {
55
+ "coverage_regression",
56
+ "coverage_drift",
57
+ "required_contract_expanded",
58
+ "required_presets_removed",
59
+ "required_invariant_families_removed",
60
+ }
61
+
62
+
63
+ class FutureAGIReplayOptimizerSchedule(BaseModel):
64
+ """Optimizer replay plan derived from Future AGI registry replay-pack triage."""
65
+
66
+ schema_version: str = FUTUREAGI_REPLAY_OPTIMIZER_SCHEDULE_SCHEMA_VERSION
67
+ provider: str = "futureagi"
68
+ should_optimize: bool
69
+ selected_optimizer: str = "none"
70
+ reason: str
71
+ replay_dataset_id: Optional[str] = None
72
+ replay_dataset_name: Optional[str] = None
73
+ registry_version: Optional[str] = None
74
+ baseline_registry_version: Optional[str] = None
75
+ triage_decision: str
76
+ triage_severity: str
77
+ triage_block_rollout: bool
78
+ triggers: list[str] = Field(default_factory=list)
79
+ optimizer_pool: list[str] = Field(default_factory=list)
80
+ max_backends: Optional[int] = None
81
+ optimizer_kwargs: dict[str, Any] = Field(default_factory=dict)
82
+ optimizer_kwargs_by_backend: dict[str, dict[str, Any]] = Field(default_factory=dict)
83
+ rollback_kwargs: dict[str, Any] = Field(default_factory=dict)
84
+ recommendations: list[str] = Field(default_factory=list)
85
+ evidence: dict[str, Any] = Field(default_factory=dict)
86
+ metadata: dict[str, Any] = Field(default_factory=dict)
87
+
88
+ def to_manifest(self) -> dict[str, Any]:
89
+ return self.model_dump()
90
+
91
+ def to_json(self, *, indent: int = 2) -> str:
92
+ return json.dumps(self.to_manifest(), sort_keys=True, indent=indent, default=str)
93
+
94
+ def to_optimizer_kwargs(self) -> dict[str, Any]:
95
+ """Arguments that can be passed to FutureAGIRegressionReplayOptimizer."""
96
+
97
+ payload: dict[str, Any] = {
98
+ "optimizer": self.selected_optimizer,
99
+ "optimizer_kwargs": copy.deepcopy(self.optimizer_kwargs),
100
+ "optimizer_kwargs_by_backend": copy.deepcopy(
101
+ self.optimizer_kwargs_by_backend
102
+ ),
103
+ "rollback_kwargs": copy.deepcopy(self.rollback_kwargs),
104
+ "optimizer_schedule": self,
105
+ }
106
+ if self.optimizer_pool:
107
+ payload["optimizer_pool"] = list(self.optimizer_pool)
108
+ if self.max_backends is not None:
109
+ payload["max_backends"] = self.max_backends
110
+ return payload
111
+
112
+
113
+ def schedule_futureagi_registry_replay_optimization(
114
+ triage: AgentRegistryReplayPackTriageReport | Mapping[str, Any],
115
+ *,
116
+ lineage: Optional[AgentRegistryReplayPackLineageReport | Mapping[str, Any]] = None,
117
+ schedule_on_review: bool = True,
118
+ force: bool = False,
119
+ optimizer_pool: Optional[Sequence[str]] = None,
120
+ max_backends: Optional[int] = None,
121
+ optimizer_kwargs: Optional[Mapping[str, Any]] = None,
122
+ optimizer_kwargs_by_backend: Optional[Mapping[str, Mapping[str, Any]]] = None,
123
+ rollback_kwargs: Optional[Mapping[str, Any]] = None,
124
+ metadata: Optional[Mapping[str, Any]] = None,
125
+ ) -> FutureAGIReplayOptimizerSchedule:
126
+ """
127
+ Convert replay-pack triage into Future AGI replay optimizer arguments.
128
+
129
+ Coverage and required-contract drift schedules curriculum replay. Optimizer
130
+ score, selected-patch, backend, or case-signature drift schedules the
131
+ multi-interaction backend portfolio. Pure Future AGI readback/promotion
132
+ evidence failures do not schedule optimizer work until the retained pack can
133
+ be read back cleanly.
134
+ """
135
+
136
+ active_triage = _coerce_futureagi_replay_triage(triage)
137
+ active_lineage = _coerce_futureagi_replay_lineage(lineage)
138
+ latest_entry = _lineage_entry_for_triage(active_lineage, active_triage)
139
+ trigger_candidates = list(active_triage.blocking_reasons)
140
+ if active_triage.block_rollout or schedule_on_review or force:
141
+ trigger_candidates.extend(active_triage.warnings)
142
+ triggers = _unique_schedule_items(trigger_candidates)
143
+ optimizer_triggers = [
144
+ trigger
145
+ for trigger in triggers
146
+ if trigger in _REPLAY_PORTFOLIO_TRIGGERS
147
+ or trigger in _REPLAY_CURRICULUM_TRIGGERS
148
+ ]
149
+ evidence_only_block = (
150
+ active_triage.block_rollout
151
+ and not optimizer_triggers
152
+ and all(trigger in _REPLAY_EVIDENCE_BLOCKERS for trigger in triggers)
153
+ )
154
+ should_optimize = bool(force or optimizer_triggers) and not evidence_only_block
155
+ selected_optimizer = "none"
156
+ reason = "no replay optimization scheduled"
157
+ schedule_optimizer_pool: list[str] = []
158
+ schedule_optimizer_kwargs = {"target_score": 1.0}
159
+ if should_optimize:
160
+ if any(trigger in _REPLAY_PORTFOLIO_TRIGGERS for trigger in optimizer_triggers):
161
+ selected_optimizer = "multi_interaction"
162
+ schedule_optimizer_pool = _unique_schedule_items(
163
+ optimizer_pool or DEFAULT_MULTI_INTERACTION_BACKENDS
164
+ )
165
+ reason = "portfolio replay for optimizer-score or selected-patch drift"
166
+ else:
167
+ selected_optimizer = "curriculum"
168
+ reason = "curriculum replay for coverage or required-contract drift"
169
+ elif evidence_only_block:
170
+ reason = "fix Future AGI readback or promotion evidence before optimizer replay"
171
+
172
+ schedule_optimizer_kwargs.update(dict(optimizer_kwargs or {}))
173
+ schedule_kwargs_by_backend = {
174
+ _normalize_optimizer_name(key): dict(value)
175
+ for key, value in dict(optimizer_kwargs_by_backend or {}).items()
176
+ }
177
+ schedule_rollback_kwargs = {
178
+ "consecutive_failures": 1,
179
+ "min_evaluations": 1,
180
+ **dict(rollback_kwargs or {}),
181
+ }
182
+ recommendations = list(active_triage.recommendations)
183
+ if should_optimize:
184
+ recommendations.append(
185
+ "Run FutureAGIRegressionReplayOptimizer with this optimizer schedule "
186
+ "against the latest retained Future AGI replay pack."
187
+ )
188
+ return FutureAGIReplayOptimizerSchedule(
189
+ should_optimize=should_optimize,
190
+ selected_optimizer=selected_optimizer,
191
+ reason=reason,
192
+ replay_dataset_id=active_triage.latest_dataset_id,
193
+ replay_dataset_name=latest_entry.dataset_name if latest_entry else None,
194
+ registry_version=active_triage.latest_registry_version,
195
+ baseline_registry_version=active_triage.baseline_registry_version,
196
+ triage_decision=active_triage.decision,
197
+ triage_severity=active_triage.severity,
198
+ triage_block_rollout=active_triage.block_rollout,
199
+ triggers=triggers,
200
+ optimizer_pool=schedule_optimizer_pool,
201
+ max_backends=max_backends,
202
+ optimizer_kwargs=schedule_optimizer_kwargs,
203
+ optimizer_kwargs_by_backend=schedule_kwargs_by_backend,
204
+ rollback_kwargs=schedule_rollback_kwargs,
205
+ recommendations=_unique_schedule_items(recommendations),
206
+ evidence={
207
+ "triage": active_triage.to_manifest(),
208
+ "lineage": active_lineage.to_manifest() if active_lineage else None,
209
+ },
210
+ metadata={
211
+ "kind": "futureagi_registry_replay_optimizer_schedule",
212
+ **dict(metadata or {}),
213
+ },
214
+ )
215
+
216
+
217
+ class FutureAGIRegressionReplayOptimizer(BaseOptimizer):
218
+ """
219
+ Re-optimize an agent from a Future AGI regression dataset.
220
+
221
+ The optimizer accepts either an already-loaded `AgentRegressionDataset` or a
222
+ Future AGI `dataset_id`, turns the regression cases into an observability
223
+ replay window, and delegates the repair search to `AgentFeedbackOptimizer`.
224
+ Use `optimizer="society"`, `"social_memory"`, `"curriculum"`,
225
+ `"council"`, `"evolution"`, `"bandit"`, `"tpe"`, `"pareto"`, or
226
+ `"agent"` to select the backend.
227
+ """
228
+
229
+ def __init__(
230
+ self,
231
+ target: Optional[OptimizationTarget] = None,
232
+ *,
233
+ dataset: Optional[AgentRegressionDataset] = None,
234
+ dataset_id: Optional[str] = None,
235
+ dataset_name: Optional[str] = None,
236
+ fi_api_key: Optional[str] = None,
237
+ fi_secret_key: Optional[str] = None,
238
+ fi_base_url: Optional[str] = None,
239
+ client: Any = None,
240
+ page_size: int = 100,
241
+ max_pages: int = 100,
242
+ timeout: float = 30.0,
243
+ candidate: Optional[AgentCandidate] = None,
244
+ deployment: Optional[AgentDeploymentExport] = None,
245
+ evaluate_candidate: Optional[CandidateScorer] = None,
246
+ simulation_evaluator: Any = None,
247
+ optimizer: str = "society",
248
+ optimizer_kwargs: Optional[Mapping[str, Any]] = None,
249
+ optimizer_pool: Optional[Sequence[str]] = None,
250
+ max_backends: Optional[int] = None,
251
+ optimizer_kwargs_by_backend: Optional[Mapping[str, Mapping[str, Any]]] = None,
252
+ optimizer_schedule: Optional[
253
+ FutureAGIReplayOptimizerSchedule | Mapping[str, Any]
254
+ ] = None,
255
+ rollback_kwargs: Optional[Mapping[str, Any]] = None,
256
+ metadata: Optional[Mapping[str, Any]] = None,
257
+ ) -> None:
258
+ self.target = target
259
+ self.dataset = dataset
260
+ self.dataset_id = dataset_id
261
+ self.dataset_name = dataset_name
262
+ self.fi_api_key = fi_api_key
263
+ self.fi_secret_key = fi_secret_key
264
+ self.fi_base_url = fi_base_url
265
+ self.client = client
266
+ self.page_size = page_size
267
+ self.max_pages = max_pages
268
+ self.timeout = timeout
269
+ self.candidate = candidate
270
+ self.deployment = deployment
271
+ self.evaluate_candidate = evaluate_candidate
272
+ self.simulation_evaluator = simulation_evaluator
273
+ self.optimizer = optimizer
274
+ self.optimizer_kwargs = dict(optimizer_kwargs or {})
275
+ self.optimizer_pool = list(optimizer_pool) if optimizer_pool is not None else None
276
+ self.max_backends = max_backends
277
+ self.optimizer_kwargs_by_backend = {
278
+ str(key): dict(value)
279
+ for key, value in dict(optimizer_kwargs_by_backend or {}).items()
280
+ }
281
+ self.optimizer_schedule = _coerce_futureagi_replay_optimizer_schedule(
282
+ optimizer_schedule
283
+ )
284
+ self.rollback_kwargs = dict(rollback_kwargs or {})
285
+ self.metadata = dict(metadata or {})
286
+ super().__init__()
287
+
288
+ def optimize(
289
+ self,
290
+ evaluator: Any = None,
291
+ data_mapper: Any = None,
292
+ dataset_records: Optional[list[dict[str, Any]]] = None,
293
+ metric: Optional[Callable] = None,
294
+ *,
295
+ target: Optional[OptimizationTarget] = None,
296
+ dataset: Optional[AgentRegressionDataset] = None,
297
+ dataset_id: Optional[str] = None,
298
+ dataset_name: Optional[str] = None,
299
+ fi_api_key: Optional[str] = None,
300
+ fi_secret_key: Optional[str] = None,
301
+ fi_base_url: Optional[str] = None,
302
+ client: Any = None,
303
+ page_size: Optional[int] = None,
304
+ max_pages: Optional[int] = None,
305
+ timeout: Optional[float] = None,
306
+ candidate: Optional[AgentCandidate] = None,
307
+ deployment: Optional[AgentDeploymentExport] = None,
308
+ evaluate_candidate: Optional[CandidateScorer] = None,
309
+ simulation_evaluator: Any = None,
310
+ optimizer: Optional[str] = None,
311
+ optimizer_kwargs: Optional[Mapping[str, Any]] = None,
312
+ optimizer_pool: Optional[Sequence[str]] = None,
313
+ max_backends: Optional[int] = None,
314
+ optimizer_kwargs_by_backend: Optional[Mapping[str, Mapping[str, Any]]] = None,
315
+ optimizer_schedule: Optional[
316
+ FutureAGIReplayOptimizerSchedule | Mapping[str, Any]
317
+ ] = None,
318
+ rollback_kwargs: Optional[Mapping[str, Any]] = None,
319
+ metadata: Optional[Mapping[str, Any]] = None,
320
+ **backend_kwargs: Any,
321
+ ) -> AgentFeedbackOptimizationResult | AgentMultiInteractionOptimizationResult:
322
+ active_target = target or self.target
323
+ if active_target is None:
324
+ raise ValueError("FutureAGIRegressionReplayOptimizer requires a target.")
325
+
326
+ active_dataset = dataset or self.dataset
327
+ active_dataset_id = dataset_id or self.dataset_id
328
+ if active_dataset is None:
329
+ if not active_dataset_id:
330
+ raise ValueError(
331
+ "FutureAGIRegressionReplayOptimizer requires dataset or dataset_id."
332
+ )
333
+ active_dataset = load_futureagi_regression_dataset(
334
+ dataset_id=active_dataset_id,
335
+ dataset_name=dataset_name or self.dataset_name,
336
+ fi_api_key=fi_api_key or self.fi_api_key,
337
+ fi_secret_key=fi_secret_key or self.fi_secret_key,
338
+ fi_base_url=fi_base_url or self.fi_base_url,
339
+ client=client or self.client,
340
+ page_size=page_size if page_size is not None else self.page_size,
341
+ max_pages=max_pages if max_pages is not None else self.max_pages,
342
+ timeout=timeout if timeout is not None else self.timeout,
343
+ metadata={
344
+ "optimizer": "FutureAGIRegressionReplayOptimizer",
345
+ **self.metadata,
346
+ **dict(metadata or {}),
347
+ },
348
+ )
349
+
350
+ active_candidate = candidate or self.candidate or active_target.seed_candidate()
351
+ active_deployment = (
352
+ deployment
353
+ or self.deployment
354
+ or export_agent_deployment(
355
+ active_candidate,
356
+ metadata={
357
+ "futureagi_regression_dataset_name": active_dataset.name,
358
+ "futureagi_regression_dataset_id": active_dataset_id,
359
+ },
360
+ )
361
+ )
362
+ replay_window = active_dataset.to_observability_window(
363
+ candidate=active_candidate,
364
+ metadata={
365
+ "futureagi_regression_replay_optimizer": True,
366
+ "futureagi_regression_dataset_id": active_dataset_id,
367
+ },
368
+ )
369
+ live_evaluations = replay_window.to_live_evaluations()
370
+ active_rollback_kwargs = {
371
+ "required_metrics": replay_window.required_metrics,
372
+ "consecutive_failures": 1,
373
+ "min_evaluations": 1,
374
+ **self.rollback_kwargs,
375
+ **dict(rollback_kwargs or {}),
376
+ }
377
+ active_schedule = (
378
+ _coerce_futureagi_replay_optimizer_schedule(optimizer_schedule)
379
+ if optimizer_schedule is not None
380
+ else self.optimizer_schedule
381
+ )
382
+ if (
383
+ active_schedule is not None
384
+ and not active_schedule.should_optimize
385
+ and optimizer is None
386
+ ):
387
+ raise ValueError(
388
+ "Future AGI replay optimizer schedule does not require "
389
+ "re-optimization."
390
+ )
391
+ schedule_optimizer_kwargs = (
392
+ copy.deepcopy(active_schedule.optimizer_kwargs)
393
+ if active_schedule is not None
394
+ else {}
395
+ )
396
+ active_optimizer_kwargs = {
397
+ **schedule_optimizer_kwargs,
398
+ **self.optimizer_kwargs,
399
+ **dict(optimizer_kwargs or {}),
400
+ **backend_kwargs,
401
+ }
402
+ active_optimizer_pool = (
403
+ list(optimizer_pool)
404
+ if optimizer_pool is not None
405
+ else (
406
+ self.optimizer_pool
407
+ if self.optimizer_pool is not None
408
+ else (
409
+ list(active_schedule.optimizer_pool)
410
+ if active_schedule is not None and active_schedule.optimizer_pool
411
+ else None
412
+ )
413
+ )
414
+ )
415
+ active_max_backends = (
416
+ max_backends
417
+ if max_backends is not None
418
+ else (
419
+ self.max_backends
420
+ if self.max_backends is not None
421
+ else (active_schedule.max_backends if active_schedule is not None else None)
422
+ )
423
+ )
424
+ schedule_kwargs_by_backend = (
425
+ copy.deepcopy(active_schedule.optimizer_kwargs_by_backend)
426
+ if active_schedule is not None
427
+ else {}
428
+ )
429
+ active_optimizer_kwargs_by_backend = {
430
+ **schedule_kwargs_by_backend,
431
+ **self.optimizer_kwargs_by_backend,
432
+ **{
433
+ str(key): dict(value)
434
+ for key, value in dict(optimizer_kwargs_by_backend or {}).items()
435
+ },
436
+ }
437
+ schedule_backend = (
438
+ active_schedule.selected_optimizer
439
+ if active_schedule is not None and active_schedule.selected_optimizer != "none"
440
+ else None
441
+ )
442
+ resolved_backend = optimizer or schedule_backend or self.optimizer
443
+ normalized_backend = _normalize_optimizer_name(resolved_backend)
444
+ if normalized_backend == "social_memory":
445
+ active_optimizer_kwargs.setdefault("experiment_history", replay_window)
446
+ if normalized_backend == "curriculum":
447
+ active_optimizer_kwargs.setdefault("curriculum_history", replay_window)
448
+ result_metadata = {
449
+ **self.metadata,
450
+ **dict(metadata or {}),
451
+ "futureagi_regression_dataset_id": active_dataset_id,
452
+ "futureagi_regression_dataset_name": active_dataset.name,
453
+ "futureagi_regression_case_count": len(active_dataset.cases),
454
+ "futureagi_replay_record_count": len(replay_window.records),
455
+ "futureagi_replay_required_metrics": dict(replay_window.required_metrics),
456
+ "futureagi_replay_required_trace_signals": list(
457
+ replay_window.required_trace_signals
458
+ ),
459
+ }
460
+ if active_schedule is not None:
461
+ result_metadata.update(
462
+ {
463
+ "futureagi_replay_optimizer_schedule": active_schedule.to_manifest(),
464
+ "futureagi_replay_scheduled_optimizer": active_schedule.selected_optimizer,
465
+ "futureagi_replay_schedule_triggers": list(active_schedule.triggers),
466
+ }
467
+ )
468
+ if normalized_backend == "multi_interaction":
469
+ active_optimizer_kwargs_by_backend.setdefault(
470
+ "social_memory",
471
+ {},
472
+ ).setdefault("experiment_history", replay_window)
473
+ active_optimizer_kwargs_by_backend.setdefault(
474
+ "curriculum",
475
+ {},
476
+ ).setdefault("curriculum_history", replay_window)
477
+ return AgentMultiInteractionOptimizer(
478
+ target=active_target,
479
+ deployment=active_deployment,
480
+ live_evaluations=live_evaluations,
481
+ evaluate_candidate=evaluate_candidate or self.evaluate_candidate or evaluator,
482
+ simulation_evaluator=simulation_evaluator or self.simulation_evaluator,
483
+ optimizer_pool=active_optimizer_pool,
484
+ max_backends=active_max_backends,
485
+ optimizer_kwargs=active_optimizer_kwargs,
486
+ optimizer_kwargs_by_backend=active_optimizer_kwargs_by_backend,
487
+ rollback_kwargs=active_rollback_kwargs,
488
+ metadata=result_metadata,
489
+ ).optimize()
490
+ return AgentFeedbackOptimizer(
491
+ target=active_target,
492
+ deployment=active_deployment,
493
+ live_evaluations=live_evaluations,
494
+ evaluate_candidate=evaluate_candidate or self.evaluate_candidate or evaluator,
495
+ simulation_evaluator=simulation_evaluator or self.simulation_evaluator,
496
+ optimizer=resolved_backend,
497
+ optimizer_kwargs=active_optimizer_kwargs,
498
+ rollback_kwargs=active_rollback_kwargs,
499
+ metadata=result_metadata,
500
+ ).optimize()
501
+
502
+
503
+ def _coerce_futureagi_replay_optimizer_schedule(
504
+ value: Optional[FutureAGIReplayOptimizerSchedule | Mapping[str, Any]],
505
+ ) -> Optional[FutureAGIReplayOptimizerSchedule]:
506
+ if value is None:
507
+ return None
508
+ if isinstance(value, FutureAGIReplayOptimizerSchedule):
509
+ return value
510
+ if isinstance(value, Mapping):
511
+ return FutureAGIReplayOptimizerSchedule(**dict(value))
512
+ raise TypeError(
513
+ "optimizer_schedule must be FutureAGIReplayOptimizerSchedule or mapping."
514
+ )
515
+
516
+
517
+ def _coerce_futureagi_replay_triage(
518
+ value: AgentRegistryReplayPackTriageReport | Mapping[str, Any],
519
+ ) -> AgentRegistryReplayPackTriageReport:
520
+ if isinstance(value, AgentRegistryReplayPackTriageReport):
521
+ return value
522
+ if isinstance(value, Mapping):
523
+ return AgentRegistryReplayPackTriageReport(**dict(value))
524
+ raise TypeError("triage must be AgentRegistryReplayPackTriageReport or mapping.")
525
+
526
+
527
+ def _coerce_futureagi_replay_lineage(
528
+ value: Optional[AgentRegistryReplayPackLineageReport | Mapping[str, Any]],
529
+ ) -> Optional[AgentRegistryReplayPackLineageReport]:
530
+ if value is None:
531
+ return None
532
+ if isinstance(value, AgentRegistryReplayPackLineageReport):
533
+ return value
534
+ if isinstance(value, Mapping):
535
+ return AgentRegistryReplayPackLineageReport(**dict(value))
536
+ raise TypeError("lineage must be AgentRegistryReplayPackLineageReport or mapping.")
537
+
538
+
539
+ def _lineage_entry_for_triage(
540
+ lineage: Optional[AgentRegistryReplayPackLineageReport],
541
+ triage: AgentRegistryReplayPackTriageReport,
542
+ ) -> Any:
543
+ if lineage is None:
544
+ return None
545
+ for entry in reversed(lineage.entries):
546
+ if triage.latest_dataset_id and entry.dataset_id == triage.latest_dataset_id:
547
+ return entry
548
+ if (
549
+ triage.latest_registry_version
550
+ and entry.registry_version == triage.latest_registry_version
551
+ ):
552
+ return entry
553
+ return lineage.entries[-1] if lineage.entries else None
554
+
555
+
556
+ def _unique_schedule_items(values: Sequence[Any]) -> list[str]:
557
+ return list(dict.fromkeys(str(value) for value in values if value))
558
+
559
+
560
+ class FutureAGIExperimentHistoryOptimizer(BaseOptimizer):
561
+ """
562
+ Re-optimize an agent from native Future AGI experiment history.
563
+
564
+ This backend reads Future AGI experiment detail/stats/row payloads, converts
565
+ variant and row-level scores into observability feedback, and delegates the
566
+ repair search to `AgentFeedbackOptimizer`. Use this when the production
567
+ signal lives in Future AGI experiments rather than regression-pack datasets.
568
+ """
569
+
570
+ def __init__(
571
+ self,
572
+ target: Optional[OptimizationTarget] = None,
573
+ *,
574
+ experiment_history: Optional[AgentObservabilityWindow] = None,
575
+ experiment_id: Optional[str] = None,
576
+ fi_api_key: Optional[str] = None,
577
+ fi_secret_key: Optional[str] = None,
578
+ fi_base_url: Optional[str] = None,
579
+ client: Any = None,
580
+ page_size: int = 100,
581
+ max_pages: int = 20,
582
+ timeout: float = 30.0,
583
+ include_rows: bool = True,
584
+ include_stats: bool = True,
585
+ prefer_v2: bool = True,
586
+ required_metrics: Optional[Mapping[str, float]] = None,
587
+ required_trace_signals: Optional[list[str]] = None,
588
+ candidate: Optional[AgentCandidate] = None,
589
+ deployment: Optional[AgentDeploymentExport] = None,
590
+ evaluate_candidate: Optional[CandidateScorer] = None,
591
+ simulation_evaluator: Any = None,
592
+ optimizer: str = "society",
593
+ optimizer_kwargs: Optional[Mapping[str, Any]] = None,
594
+ optimizer_pool: Optional[Sequence[str]] = None,
595
+ max_backends: Optional[int] = None,
596
+ optimizer_kwargs_by_backend: Optional[Mapping[str, Mapping[str, Any]]] = None,
597
+ rollback_kwargs: Optional[Mapping[str, Any]] = None,
598
+ metadata: Optional[Mapping[str, Any]] = None,
599
+ ) -> None:
600
+ self.target = target
601
+ self.experiment_history = experiment_history
602
+ self.experiment_id = experiment_id
603
+ self.fi_api_key = fi_api_key
604
+ self.fi_secret_key = fi_secret_key
605
+ self.fi_base_url = fi_base_url
606
+ self.client = client
607
+ self.page_size = page_size
608
+ self.max_pages = max_pages
609
+ self.timeout = timeout
610
+ self.include_rows = include_rows
611
+ self.include_stats = include_stats
612
+ self.prefer_v2 = prefer_v2
613
+ self.required_metrics = dict(required_metrics or {})
614
+ self.required_trace_signals = list(required_trace_signals or [])
615
+ self.candidate = candidate
616
+ self.deployment = deployment
617
+ self.evaluate_candidate = evaluate_candidate
618
+ self.simulation_evaluator = simulation_evaluator
619
+ self.optimizer = optimizer
620
+ self.optimizer_kwargs = dict(optimizer_kwargs or {})
621
+ self.optimizer_pool = list(optimizer_pool) if optimizer_pool is not None else None
622
+ self.max_backends = max_backends
623
+ self.optimizer_kwargs_by_backend = {
624
+ str(key): dict(value)
625
+ for key, value in dict(optimizer_kwargs_by_backend or {}).items()
626
+ }
627
+ self.rollback_kwargs = dict(rollback_kwargs or {})
628
+ self.metadata = dict(metadata or {})
629
+ super().__init__()
630
+
631
+ def optimize(
632
+ self,
633
+ evaluator: Any = None,
634
+ data_mapper: Any = None,
635
+ dataset_records: Optional[list[dict[str, Any]]] = None,
636
+ metric: Optional[Callable] = None,
637
+ *,
638
+ target: Optional[OptimizationTarget] = None,
639
+ experiment_history: Optional[AgentObservabilityWindow] = None,
640
+ experiment_id: Optional[str] = None,
641
+ fi_api_key: Optional[str] = None,
642
+ fi_secret_key: Optional[str] = None,
643
+ fi_base_url: Optional[str] = None,
644
+ client: Any = None,
645
+ page_size: Optional[int] = None,
646
+ max_pages: Optional[int] = None,
647
+ timeout: Optional[float] = None,
648
+ include_rows: Optional[bool] = None,
649
+ include_stats: Optional[bool] = None,
650
+ prefer_v2: Optional[bool] = None,
651
+ required_metrics: Optional[Mapping[str, float]] = None,
652
+ required_trace_signals: Optional[list[str]] = None,
653
+ candidate: Optional[AgentCandidate] = None,
654
+ deployment: Optional[AgentDeploymentExport] = None,
655
+ evaluate_candidate: Optional[CandidateScorer] = None,
656
+ simulation_evaluator: Any = None,
657
+ optimizer: Optional[str] = None,
658
+ optimizer_kwargs: Optional[Mapping[str, Any]] = None,
659
+ optimizer_pool: Optional[Sequence[str]] = None,
660
+ max_backends: Optional[int] = None,
661
+ optimizer_kwargs_by_backend: Optional[Mapping[str, Mapping[str, Any]]] = None,
662
+ rollback_kwargs: Optional[Mapping[str, Any]] = None,
663
+ metadata: Optional[Mapping[str, Any]] = None,
664
+ **backend_kwargs: Any,
665
+ ) -> AgentFeedbackOptimizationResult | AgentMultiInteractionOptimizationResult:
666
+ active_target = target or self.target
667
+ if active_target is None:
668
+ raise ValueError("FutureAGIExperimentHistoryOptimizer requires a target.")
669
+
670
+ active_candidate = candidate or self.candidate or active_target.seed_candidate()
671
+ active_history = experiment_history or self.experiment_history
672
+ active_experiment_id = experiment_id or self.experiment_id
673
+ active_required_metrics = {
674
+ **self.required_metrics,
675
+ **dict(required_metrics or {}),
676
+ }
677
+ active_required_signals = list(
678
+ required_trace_signals
679
+ if required_trace_signals is not None
680
+ else self.required_trace_signals
681
+ )
682
+ if active_history is None:
683
+ if not active_experiment_id:
684
+ raise ValueError(
685
+ "FutureAGIExperimentHistoryOptimizer requires "
686
+ "experiment_history or experiment_id."
687
+ )
688
+ active_history = load_futureagi_experiment_history(
689
+ experiment_id=active_experiment_id,
690
+ candidate=active_candidate,
691
+ required_metrics=active_required_metrics,
692
+ required_trace_signals=active_required_signals,
693
+ fi_api_key=fi_api_key or self.fi_api_key,
694
+ fi_secret_key=fi_secret_key or self.fi_secret_key,
695
+ fi_base_url=fi_base_url or self.fi_base_url,
696
+ client=client or self.client,
697
+ page_size=page_size if page_size is not None else self.page_size,
698
+ max_pages=max_pages if max_pages is not None else self.max_pages,
699
+ timeout=timeout if timeout is not None else self.timeout,
700
+ include_rows=include_rows if include_rows is not None else self.include_rows,
701
+ include_stats=include_stats if include_stats is not None else self.include_stats,
702
+ prefer_v2=prefer_v2 if prefer_v2 is not None else self.prefer_v2,
703
+ metadata={
704
+ "optimizer": "FutureAGIExperimentHistoryOptimizer",
705
+ **self.metadata,
706
+ **dict(metadata or {}),
707
+ },
708
+ )
709
+
710
+ resolved_experiment_id = active_experiment_id or str(
711
+ active_history.metadata.get("experiment_id") or ""
712
+ )
713
+ active_deployment = (
714
+ deployment
715
+ or self.deployment
716
+ or export_agent_deployment(
717
+ active_candidate,
718
+ metadata={
719
+ "futureagi_experiment_id": resolved_experiment_id,
720
+ "futureagi_experiment_name": active_history.metadata.get(
721
+ "experiment_name"
722
+ ),
723
+ },
724
+ )
725
+ )
726
+ live_evaluations = active_history.to_live_evaluations(candidate=active_candidate)
727
+ active_rollback_kwargs = {
728
+ "required_metrics": active_history.required_metrics,
729
+ "consecutive_failures": 1,
730
+ "min_evaluations": 1,
731
+ **self.rollback_kwargs,
732
+ **dict(rollback_kwargs or {}),
733
+ }
734
+ active_optimizer_kwargs = {
735
+ **self.optimizer_kwargs,
736
+ **dict(optimizer_kwargs or {}),
737
+ **backend_kwargs,
738
+ }
739
+ active_optimizer_pool = (
740
+ list(optimizer_pool) if optimizer_pool is not None else self.optimizer_pool
741
+ )
742
+ active_max_backends = self.max_backends if max_backends is None else max_backends
743
+ active_optimizer_kwargs_by_backend = {
744
+ **self.optimizer_kwargs_by_backend,
745
+ **{
746
+ str(key): dict(value)
747
+ for key, value in dict(optimizer_kwargs_by_backend or {}).items()
748
+ },
749
+ }
750
+ resolved_backend = optimizer or self.optimizer
751
+ normalized_backend = _normalize_optimizer_name(resolved_backend)
752
+ if normalized_backend == "social_memory":
753
+ active_optimizer_kwargs.setdefault("experiment_history", active_history)
754
+ if normalized_backend == "curriculum":
755
+ active_optimizer_kwargs.setdefault("curriculum_history", active_history)
756
+ result_metadata = {
757
+ **self.metadata,
758
+ **dict(metadata or {}),
759
+ "futureagi_experiment_id": resolved_experiment_id,
760
+ "futureagi_experiment_name": active_history.metadata.get("experiment_name"),
761
+ "futureagi_experiment_record_count": len(active_history.records),
762
+ "futureagi_experiment_required_metrics": dict(active_history.required_metrics),
763
+ "futureagi_experiment_required_trace_signals": list(
764
+ active_history.required_trace_signals
765
+ ),
766
+ }
767
+ if normalized_backend == "multi_interaction":
768
+ active_optimizer_kwargs_by_backend.setdefault(
769
+ "social_memory",
770
+ {},
771
+ ).setdefault("experiment_history", active_history)
772
+ active_optimizer_kwargs_by_backend.setdefault(
773
+ "curriculum",
774
+ {},
775
+ ).setdefault("curriculum_history", active_history)
776
+ return AgentMultiInteractionOptimizer(
777
+ target=active_target,
778
+ deployment=active_deployment,
779
+ live_evaluations=live_evaluations,
780
+ evaluate_candidate=evaluate_candidate or self.evaluate_candidate or evaluator,
781
+ simulation_evaluator=simulation_evaluator or self.simulation_evaluator,
782
+ optimizer_pool=active_optimizer_pool,
783
+ max_backends=active_max_backends,
784
+ optimizer_kwargs=active_optimizer_kwargs,
785
+ optimizer_kwargs_by_backend=active_optimizer_kwargs_by_backend,
786
+ rollback_kwargs=active_rollback_kwargs,
787
+ metadata=result_metadata,
788
+ ).optimize()
789
+ return AgentFeedbackOptimizer(
790
+ target=active_target,
791
+ deployment=active_deployment,
792
+ live_evaluations=live_evaluations,
793
+ evaluate_candidate=evaluate_candidate or self.evaluate_candidate or evaluator,
794
+ simulation_evaluator=simulation_evaluator or self.simulation_evaluator,
795
+ optimizer=resolved_backend,
796
+ optimizer_kwargs=active_optimizer_kwargs,
797
+ rollback_kwargs=active_rollback_kwargs,
798
+ metadata=result_metadata,
799
+ ).optimize()