agentcore-rl-toolkit 0.1.2__tar.gz → 0.1.4__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 (216) hide show
  1. agentcore_rl_toolkit-0.1.4/.gitignore +49 -0
  2. agentcore_rl_toolkit-0.1.4/NOTICE +29 -0
  3. agentcore_rl_toolkit-0.1.2/README.md → agentcore_rl_toolkit-0.1.4/PKG-INFO +152 -24
  4. agentcore_rl_toolkit-0.1.2/PKG-INFO → agentcore_rl_toolkit-0.1.4/README.md +74 -52
  5. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/blog/async-rl-performance-optimization/async_rl.png +0 -0
  6. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/blog/async-rl-performance-optimization/inference_throughput_and_concurrency.png +0 -0
  7. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/blog/async-rl-performance-optimization/reward_curve.png +0 -0
  8. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/blog/async-rl-performance-optimization/rollout_corr_eff_sample_size.png +0 -0
  9. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/blog/async-rl-performance-optimization/sync_rl.png +0 -0
  10. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/blog/data-synthesis-v0/fig_action_difficulty_depth.png +0 -0
  11. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/blog/data-synthesis-v0/fig_cost_vs_performance.png +0 -0
  12. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/blog/data-synthesis-v0/fig_rl_buckets_telecom.png +0 -0
  13. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/blog/data-synthesis-v0/fig_system_workflow.png +0 -0
  14. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/blog/variable-rows-linear-mode/linear-efficiency.png +0 -0
  15. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/blog/variable-rows-linear-mode/optimizer-reward.png +0 -0
  16. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/examples/openhands-swegym-agent/latency_breakdown.png +0 -0
  17. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/examples/openhands-swegym-agent/reward_curve.png +0 -0
  18. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/examples/openhands-swegym-agent/setup_run_pipeline.png +0 -0
  19. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/examples/openhands-swegym-agent/swe_agent_design.png +0 -0
  20. agentcore_rl_toolkit-0.1.4/docs/site/src/assets/houston.webp +0 -0
  21. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/api/backends/slime/runner.md +176 -0
  22. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/api/core/app.md +85 -0
  23. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/api/core/client.md +412 -0
  24. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/api/core/reward.md +45 -0
  25. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/api/index.md +20 -0
  26. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/blog/async-rl-performance-optimization.md +111 -0
  27. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/blog/data-synthesis-v0.mdx +439 -0
  28. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/blog/index.mdx +19 -0
  29. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/blog/training-multi-step-agents-rl.mdx +410 -0
  30. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/blog/variable-rows-linear-mode.mdx +312 -0
  31. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/examples/index.mdx +31 -0
  32. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/examples/openhands-swegym-agent.md +277 -0
  33. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/examples/strands-appworld-agent.md +50 -0
  34. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/examples/strands-math-agent.md +42 -0
  35. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/examples/strands-migration-agent.md +57 -0
  36. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/examples/strands-officebench-agent.md +72 -0
  37. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/guides/agent-adaptation.mdx +183 -0
  38. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/guides/overview.mdx +190 -0
  39. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/guides/rllm-backend-setup.md +101 -0
  40. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/guides/slime-backend-setup.md +131 -0
  41. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/guides/verl-backend-setup.md +141 -0
  42. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/index.mdx +116 -0
  43. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/troubleshooting/rllm.md +14 -0
  44. agentcore_rl_toolkit-0.1.4/docs/site/src/content/docs/troubleshooting/slime.md +32 -0
  45. agentcore_rl_toolkit-0.1.4/docs/site/src/content.config.ts +7 -0
  46. agentcore_rl_toolkit-0.1.4/docs/site/src/styles/custom.css +610 -0
  47. agentcore_rl_toolkit-0.1.4/examples/openhands_swe_agent/src/swe_agent_server/app.py +62 -0
  48. agentcore_rl_toolkit-0.1.4/examples/openhands_swe_agent/src/swe_agent_server/evaluation.py +156 -0
  49. agentcore_rl_toolkit-0.1.4/examples/openhands_swe_agent/src/swe_agent_server/noop_agent.py +43 -0
  50. agentcore_rl_toolkit-0.1.4/examples/openhands_swe_agent/src/swe_agent_server/observability.py +312 -0
  51. agentcore_rl_toolkit-0.1.4/examples/openhands_swe_agent/src/swe_agent_server/open_hands_agent.py +247 -0
  52. agentcore_rl_toolkit-0.1.4/examples/openhands_swe_agent/src/swe_agent_server/oracle_agent.py +55 -0
  53. agentcore_rl_toolkit-0.1.4/examples/openhands_swe_agent/src/swe_agent_server/prompts/benchmarks_r2.j2 +64 -0
  54. agentcore_rl_toolkit-0.1.4/examples/openhands_swe_agent/src/swe_agent_server/prompts/empty.j2 +0 -0
  55. agentcore_rl_toolkit-0.1.4/examples/openhands_swe_agent/src/swe_agent_server/prompts/system_prompt.j2 +1 -0
  56. agentcore_rl_toolkit-0.1.4/examples/openhands_swe_agent/src/swe_agent_server/rollout.py +87 -0
  57. agentcore_rl_toolkit-0.1.4/examples/openhands_swe_agent/src/swe_agent_server/strands_agent.py +263 -0
  58. agentcore_rl_toolkit-0.1.4/examples/openhands_swe_agent/src/swe_agent_server/utils.py +15 -0
  59. agentcore_rl_toolkit-0.1.4/pyproject.toml +267 -0
  60. {agentcore_rl_toolkit-0.1.2 → agentcore_rl_toolkit-0.1.4}/src/agentcore_rl_toolkit/__init__.py +5 -0
  61. {agentcore_rl_toolkit-0.1.2 → agentcore_rl_toolkit-0.1.4}/src/agentcore_rl_toolkit/app.py +31 -14
  62. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/aws_tools/__init__.py +6 -0
  63. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/aws_tools/agentcore_control.py +366 -0
  64. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/aws_tools/agentcore_tools.py +265 -0
  65. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/aws_tools/boto3_tools.py +273 -0
  66. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/aws_tools/dynamodb_control.py +162 -0
  67. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/aws_tools/dynamodb_tools.py +154 -0
  68. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/aws_tools/ec2_monitor.py +230 -0
  69. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/aws_tools/ec2_tools.py +83 -0
  70. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/aws_tools/ecr_control.py +200 -0
  71. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/aws_tools/iam_control.py +184 -0
  72. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/aws_tools/persistent_dict.py +197 -0
  73. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/aws_tools/s3_tools.py +12 -0
  74. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/__init__.py +0 -0
  75. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/__init__.py +6 -0
  76. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/slime/__init__.py +0 -0
  77. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/slime/examples/math_agent/SETUP.md +36 -0
  78. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/slime/examples/math_agent/config.yaml.example +24 -0
  79. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/slime/examples/math_agent/train.sh +132 -0
  80. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/slime/integration/__init__.py +0 -0
  81. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/slime/integration/rewards.py +49 -0
  82. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/slime/integration/rollout.py +202 -0
  83. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/slime/scripts/install_slime.sh +86 -0
  84. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/verl/__init__.py +6 -0
  85. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/verl/config.py +51 -0
  86. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/verl/rollout_session_agent_loop.py +595 -0
  87. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/verl/rollout_session_resources.py +125 -0
  88. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/experimental/verl/task_runner.py +30 -0
  89. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/SETUP.md +283 -0
  90. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/__init__.py +12 -0
  91. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/examples/math_agent/.wandb.env.example +23 -0
  92. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/examples/math_agent/config.yaml.example +46 -0
  93. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/examples/math_agent/eval.sh +175 -0
  94. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/examples/math_agent/train.py +22 -0
  95. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/examples/math_agent/train.sh +153 -0
  96. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/integration/__init__.py +0 -0
  97. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/integration/gateway.py +178 -0
  98. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/integration/rewards.py +102 -0
  99. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/integration/rollout.py +520 -0
  100. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/integration/traces.py +288 -0
  101. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/runner.py +379 -0
  102. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/slime/scripts/install_slime.sh +118 -0
  103. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/README.md +102 -0
  104. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/__init__.py +1 -0
  105. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/data.py +114 -0
  106. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/examples/math_agent/config.json.example +27 -0
  107. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/examples/math_agent/prepare_data.py +26 -0
  108. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/skyrl/.gitignore +4 -0
  109. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/skyrl/README.md +133 -0
  110. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/skyrl/aws_setup.py +238 -0
  111. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/skyrl/backend_config.json +32 -0
  112. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/skyrl/deploy.py +205 -0
  113. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/skyrl/endpoint.yaml +22 -0
  114. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/skyrl/environment.sh +22 -0
  115. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/skyrl/pyproject.toml +13 -0
  116. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/skyrl/serve.sh +20 -0
  117. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/skyrl/setup.sh +27 -0
  118. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/tinker_api/train.py +434 -0
  119. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/README.md +306 -0
  120. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/__init__.py +24 -0
  121. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/agent_loop.py +448 -0
  122. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/dataset.py +70 -0
  123. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/math_agent/agentcore_agent.yaml +33 -0
  124. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/math_agent/fsdp_fft_sync_grpo.sh +109 -0
  125. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/math_agent/fsdp_lora_sync_grpo.sh +82 -0
  126. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/math_agent/megatron_lora_sync_grpo.sh +96 -0
  127. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/math_agent/preprocess_gsm8k.py +64 -0
  128. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/migration_agent/README.md +44 -0
  129. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/migration_agent/agentcore_agent.yaml +16 -0
  130. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/migration_agent/megatron_lora_sync_grpo_qwen3-coder-30b-a3b.sh +154 -0
  131. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/migration_agent/megatron_lora_sync_grpo_qwen3.6-27b.sh +128 -0
  132. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/migration_agent/preprocess_migrationbench.py +127 -0
  133. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/README.md +213 -0
  134. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/async_separate_b1.yaml +10 -0
  135. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/async_separate_b2.yaml +10 -0
  136. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/cluster_hybrid.yaml +5 -0
  137. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/cluster_trainer2_rollout1.yaml +15 -0
  138. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/cluster_trainer_rollout_n1.yaml +12 -0
  139. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/cluster_trainer_rollout_n2.yaml +15 -0
  140. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/cluster_trainer_rollout_n4.yaml +15 -0
  141. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/dataset_swe_gym.yaml +15 -0
  142. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/lora.yaml +14 -0
  143. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/main.yaml +33 -0
  144. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/megatron.yaml +6 -0
  145. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/megatron_offload.yaml +8 -0
  146. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/megatron_recompute.yaml +11 -0
  147. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/qwen3_30b_p5.yaml +36 -0
  148. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/qwen3_30b_p6.yaml +39 -0
  149. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/rollout_correction_decoupled.yaml +9 -0
  150. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/rollout_session_agent_loop.yaml +57 -0
  151. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/smart_ppo.yaml +58 -0
  152. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/sync_b1.yaml +9 -0
  153. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/config/sync_b2.yaml +9 -0
  154. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/examples/swe_agent/main.py +44 -0
  155. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/gateway_host.py +202 -0
  156. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/sampling_backend.py +124 -0
  157. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/trainer.py +89 -0
  158. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/trainer_mixins/__init__.py +13 -0
  159. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/trainer_mixins/advantage_metrics.py +107 -0
  160. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/trainer_mixins/agent_loop_metrics.py +101 -0
  161. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/trainer_mixins/base.py +25 -0
  162. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/trainer_mixins/round_robin_agent_loop_dispatch.py +53 -0
  163. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/backends/verl/trainer_mixins/variable_row_batching.py +149 -0
  164. {agentcore_rl_toolkit-0.1.2 → agentcore_rl_toolkit-0.1.4}/src/agentcore_rl_toolkit/client.py +48 -34
  165. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/concurrency/__init__.py +5 -0
  166. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/concurrency/priority_assigner.py +31 -0
  167. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/concurrency/priority_semaphore.py +124 -0
  168. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/concurrency/rate_limiter.py +65 -0
  169. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/concurrency/ray_adapters.py +88 -0
  170. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/logging.py +58 -0
  171. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/__init__.py +54 -0
  172. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/adapters/__init__.py +7 -0
  173. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/adapters/anthropic.py +357 -0
  174. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/adapters/common.py +537 -0
  175. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/adapters/openai.py +382 -0
  176. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/gateway.py +152 -0
  177. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/linear.py +316 -0
  178. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/parsing.py +100 -0
  179. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/render.py +395 -0
  180. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/response_schemas.py +270 -0
  181. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/sampling_backends/__init__.py +14 -0
  182. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/sampling_backends/base.py +36 -0
  183. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/sampling_backends/sglang_http.py +89 -0
  184. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/sampling_backends/tinker_sdk.py +66 -0
  185. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/sampling_backends/vllm_http.py +133 -0
  186. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/server.py +118 -0
  187. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/trace.py +81 -0
  188. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_gateway/trajectory.py +427 -0
  189. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/__init__.py +5 -0
  190. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/a2a_client.py +284 -0
  191. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/a2a_executor.py +124 -0
  192. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/a2a_protocol.py +109 -0
  193. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/agentcore_a2a_session.py +82 -0
  194. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/agentcore_http_session.py +70 -0
  195. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/agentcore_s3_session.py +376 -0
  196. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/docker_a2a_session.py +139 -0
  197. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/errors.py +31 -0
  198. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/exception_utils.py +53 -0
  199. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/factory.py +89 -0
  200. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/lifecycle.py +120 -0
  201. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/rollout_session/wire.py +29 -0
  202. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/runtime/__init__.py +6 -0
  203. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/runtime/app.py +132 -0
  204. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/runtime/client.py +213 -0
  205. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/runtime/protocol.py +53 -0
  206. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/runtime/store.py +54 -0
  207. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/sandbox/__init__.py +18 -0
  208. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/sandbox/client.py +430 -0
  209. agentcore_rl_toolkit-0.1.4/src/agentcore_rl_toolkit/sandbox/types.py +36 -0
  210. agentcore_rl_toolkit-0.1.2/.gitignore +0 -23
  211. agentcore_rl_toolkit-0.1.2/NOTICE +0 -1
  212. agentcore_rl_toolkit-0.1.2/pyproject.toml +0 -57
  213. agentcore_rl_toolkit-0.1.2/src/agentcore_rl_toolkit/frameworks/strands/__init__.py +0 -3
  214. agentcore_rl_toolkit-0.1.2/src/agentcore_rl_toolkit/frameworks/strands/vllm_model.py +0 -110
  215. {agentcore_rl_toolkit-0.1.2 → agentcore_rl_toolkit-0.1.4}/LICENSE +0 -0
  216. {agentcore_rl_toolkit-0.1.2 → agentcore_rl_toolkit-0.1.4}/src/agentcore_rl_toolkit/reward_function.py +0 -0
@@ -0,0 +1,49 @@
1
+ # Virtual environments
2
+ .venv/
3
+ .venv-*/
4
+
5
+ # Python cache
6
+ __pycache__/
7
+ .ruff_cache/
8
+ .pytest_cache/
9
+
10
+ # Build artifacts
11
+ *.egg-info/
12
+ dist/
13
+ build/
14
+
15
+ # Environment variables
16
+ .env
17
+ .wandb.env
18
+
19
+ # Logs and experiment tracking
20
+ wandb/
21
+ *.log
22
+
23
+ # Local slime backend config (contains ARN/bucket; commit config.yaml.example only)
24
+ src/agentcore_rl_toolkit/backends/slime/examples/**/config.yaml
25
+ src/agentcore_rl_toolkit/backends/experimental/slime/examples/**/config.yaml
26
+
27
+ # Training/example run artifacts, wherever generated. Convention-level patterns:
28
+ # hydra run dirs, verl checkpoint dirs (scripts use CKPTS_DIR=exp_*), wandb run
29
+ # dirs, and generated datasets (reproducible via the example preprocess scripts).
30
+ outputs/
31
+ checkpoints/
32
+ exp_*/
33
+ wandb/
34
+ *.parquet
35
+ local/
36
+
37
+ # Config files
38
+ config.toml
39
+
40
+ # Claude Code configuration: ignore everything by default,
41
+ # allowlist only skills meant to ship with the repo.
42
+ .claude/*
43
+ !.claude/skills/
44
+ .claude/skills/*
45
+ !.claude/skills/check-cloudwatch-session-logs/
46
+ # Personal per-project Claude instructions (loaded alongside CLAUDE.md, never committed)
47
+ CLAUDE.local.md
48
+
49
+ .bedrock_agentcore.yaml
@@ -0,0 +1,29 @@
1
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+
3
+ ------------------------------------------------------------------------------
4
+
5
+ This product includes software developed as part of the slime project
6
+ (https://github.com/THUDM/slime), licensed under the Apache License, Version 2.0.
7
+
8
+ The rollout gateway (src/agentcore_rl_toolkit/rollout_gateway/) adapts code from
9
+ slime, notably:
10
+ - trajectory.py — TrajectoryManager, TurnRecord, MessageNode, and the
11
+ CLEAN/FORK drift classification, adapted from
12
+ slime/agent/trajectory.py (made torch-free).
13
+ - adapters/ — OpenAIAdapter, AnthropicAdapter, and the shared BaseAdapter
14
+ pipeline, adapted from slime/agent/adapters/.
15
+ - parsing.py — output-parsing helpers, adapted from slime/agent/parsing.py.
16
+ - server.py — background-thread serving mechanics and FilteredAccessLogger,
17
+ adapted from slime/agent/aiohttp_threaded.py.
18
+
19
+ ------------------------------------------------------------------------------
20
+
21
+ This product includes data developed as part of the TRL project
22
+ (https://github.com/huggingface/trl), licensed under the Apache License,
23
+ Version 2.0.
24
+
25
+ The rollout gateway's response-schema registry
26
+ (src/agentcore_rl_toolkit/rollout_gateway/response_schemas.py) vendors the
27
+ response-schema dicts from trl/chat_template_utils.py and derives its
28
+ chat-template hash table from trl/chat_templates/*.jinja (baseline commit
29
+ 7073af94).
@@ -1,3 +1,81 @@
1
+ Metadata-Version: 2.5
2
+ Name: agentcore-rl-toolkit
3
+ Version: 0.1.4
4
+ Summary: Toolkit for Seamlessly Enabling RL Training with Bedrock AgentCore.
5
+ Project-URL: Homepage, https://github.com/awslabs/agentcore-rl-toolkit
6
+ Author-email: Amazon Web Services - Labs <opensource@amazon.com>
7
+ License-Expression: Apache-2.0
8
+ License-File: LICENSE
9
+ License-File: NOTICE
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: License :: OSI Approved :: Apache Software License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Requires-Python: >=3.11
17
+ Requires-Dist: bedrock-agentcore-starter-toolkit>=0.2.0
18
+ Requires-Dist: bedrock-agentcore>=1.23.1
19
+ Requires-Dist: boto3>=1.40.55
20
+ Requires-Dist: python-dotenv>=1.0.0
21
+ Provides-Extra: a2a
22
+ Requires-Dist: a2a-sdk[http-server]<2.0,>=1.0.1; extra == 'a2a'
23
+ Requires-Dist: aioboto3>=15.5.0; extra == 'a2a'
24
+ Requires-Dist: aiohttp>=3.9; extra == 'a2a'
25
+ Requires-Dist: backoff; extra == 'a2a'
26
+ Requires-Dist: httpx>=0.27.0; extra == 'a2a'
27
+ Requires-Dist: pydantic; extra == 'a2a'
28
+ Provides-Extra: a2a-server
29
+ Requires-Dist: a2a-sdk[http-server]<2.0,>=1.0.1; extra == 'a2a-server'
30
+ Provides-Extra: dev
31
+ Requires-Dist: a2a-sdk[http-server]<2.0,>=1.0.1; extra == 'dev'
32
+ Requires-Dist: aioboto3>=15.5.0; extra == 'dev'
33
+ Requires-Dist: aiohttp>=3.9; extra == 'dev'
34
+ Requires-Dist: backoff; extra == 'dev'
35
+ Requires-Dist: httpx>=0.27.0; extra == 'dev'
36
+ Requires-Dist: mypy>=1.0; extra == 'dev'
37
+ Requires-Dist: openai>=1.0; extra == 'dev'
38
+ Requires-Dist: pre-commit>=3.0; extra == 'dev'
39
+ Requires-Dist: pydantic; extra == 'dev'
40
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
41
+ Requires-Dist: pytest>=7.0; extra == 'dev'
42
+ Requires-Dist: tokenizers>=0.22.2; extra == 'dev'
43
+ Requires-Dist: transformers>=5.0; extra == 'dev'
44
+ Provides-Extra: gateway
45
+ Requires-Dist: aiohttp>=3.9; extra == 'gateway'
46
+ Requires-Dist: jmespath>=1.0; extra == 'gateway'
47
+ Requires-Dist: tokenizers>=0.22.2; extra == 'gateway'
48
+ Requires-Dist: transformers>=5.0; extra == 'gateway'
49
+ Provides-Extra: rllm
50
+ Requires-Dist: rllm; extra == 'rllm'
51
+ Provides-Extra: rollout
52
+ Requires-Dist: aioboto3>=15.5.0; extra == 'rollout'
53
+ Requires-Dist: aiohttp>=3.9; extra == 'rollout'
54
+ Requires-Dist: backoff; extra == 'rollout'
55
+ Requires-Dist: httpx>=0.27.0; extra == 'rollout'
56
+ Requires-Dist: pydantic; extra == 'rollout'
57
+ Provides-Extra: slime
58
+ Requires-Dist: rllm-model-gateway>=0.1.0; extra == 'slime'
59
+ Provides-Extra: tinker-api
60
+ Requires-Dist: tinker==0.30.1; extra == 'tinker-api'
61
+ Provides-Extra: tinker-skyrl
62
+ Requires-Dist: tinker==0.24.1; extra == 'tinker-skyrl'
63
+ Provides-Extra: verl
64
+ Requires-Dist: aiohttp>=3.9; extra == 'verl'
65
+ Requires-Dist: flash-attn==2.8.3; extra == 'verl'
66
+ Requires-Dist: flash-linear-attention>=0.5.2; extra == 'verl'
67
+ Requires-Dist: numpy; extra == 'verl'
68
+ Requires-Dist: orjson; extra == 'verl'
69
+ Requires-Dist: qwen-vl-utils; extra == 'verl'
70
+ Requires-Dist: ray; extra == 'verl'
71
+ Requires-Dist: torch>=2.10.0; extra == 'verl'
72
+ Requires-Dist: torchvision>=0.23.0; extra == 'verl'
73
+ Requires-Dist: transferqueue==0.1.8; extra == 'verl'
74
+ Requires-Dist: transformers==5.12.1; extra == 'verl'
75
+ Requires-Dist: verl==0.9.0; extra == 'verl'
76
+ Requires-Dist: vllm==0.24.0; extra == 'verl'
77
+ Description-Content-Type: text/markdown
78
+
1
79
 
2
80
  # AgentCore RL Toolkit (ART)
3
81
 
@@ -5,12 +83,12 @@ Toolkit to Seamlessly Enable RL Training on Any Agent with Bedrock AgentCore.
5
83
 
6
84
  ## Overview
7
85
 
8
- **AgentCore RL Toolkit (ART)** is an SDK that helps developers adapt their production LLM agents for online RL training with **AWS Bedrock AgentCore Runtime (ACR)**. It extends [bedrock-agentcore-sdk-python](https://github.com/aws/bedrock-agentcore-sdk-python/tree/main) so most of your production agent code can be directly reused.
86
+ **AgentCore RL Toolkit (ART)** is an SDK that helps developers adapt their production LLM agents for RL training with **AWS Bedrock AgentCore Runtime (ACR)**. It extends [bedrock-agentcore-sdk-python](https://github.com/aws/bedrock-agentcore-sdk-python/tree/main) so most of your production agent code can be directly reused.
9
87
 
10
88
  LLM agent rollouts are long-running — an agent may run for minutes or hours making tool calls. The toolkit manages this with an async-first design:
11
89
 
12
- - **Agent Adaptation** (`AgentCoreRLApp`, `vLLMModel`): Adapt your production agent for RL training inside ACR — the `@rollout_entrypoint` decorator runs your agent in the background with fire-and-forget semantics, collecting token-level data, computing rewards, and saving results to S3.
13
- - **Simplified Rollout Collection** (`RolloutClient`, `RolloutFuture`): Submit rollout requests and collect results asynchronously with a future-based API, built-in concurrency control, rate limiting, and S3 polling — for both training loops and batch evaluation.
90
+ - **Agent Adaptation** (`AgentCoreRLApp`, `@rollout_entrypoint`): A decorator swap turns your production agent into an async, fire-and-forget service — the agent runs in the background and saves results to S3. Return any JSON-serializable artifacts: rewards for RL training, evaluation metrics, conversation history, or custom data.
91
+ - **Rollout Collection** (`RolloutClient`, `RolloutFuture`): Submit requests and collect results asynchronously with a future-based API, built-in concurrency control, rate limiting, and S3 polling — for both training loops and batch evaluation.
14
92
 
15
93
  Both components use S3 as their data layer, but the complexity is fully abstracted — your code never reads from or writes to S3 directly.
16
94
 
@@ -40,11 +118,12 @@ While session routing is valuable for multi-turn production agents, RL rollouts
40
118
 
41
119
  ## Key Features
42
120
 
43
- - **Minimal code changes**: Adapt your production agent with a decorator swap (`@app.entrypoint` → `@app.rollout_entrypoint`) and model replacement — most of your agent code stays the same
44
- - **Token-accurate rollout data**: `vLLMModel` collects token IDs and logprobs directly from the inference server, avoiding retokenization issues that cause training instability
121
+ - **Minimal code changes**: Adapt your production agent with a decorator swap (`@app.entrypoint` → `@app.rollout_entrypoint`) — most of your agent code stays the same
122
+ - **No custom model wrappers**: Your agent uses standard framework models (e.g., `OpenAIModel`). Token capture for RL training is handled at the infrastructure layer, not in your agent code
45
123
  - **Async end-to-end**: Fire-and-forget server + future-based client — no long-lived TCP connections needed for long-running agent rollouts
46
124
  - **Simplified rollout collection**: `RolloutClient` manages concurrency, rate limiting, and S3 result polling out of the box for both training loops and batch evaluation
47
125
  - **Production parity**: Direct code reuse from production agents ensures training behavior matches real deployment
126
+ - **Sandbox on ACR** (`SandboxClient` + `agentcore-sandboxd`): Run shell commands in arbitrary Docker images (e.g. SWE-bench-style coding environments) as isolated AgentCore runtime sessions — no agent server required in the image
48
127
 
49
128
  ## Agent-Side: Adapting Your Agent for RL
50
129
 
@@ -79,8 +158,8 @@ if __name__ == "__main__":
79
158
  Starting from a deployment-ready agent like above, here are the changes needed for RL training (see [`rl_app.py`](examples/strands_math_agent/rl_app.py) for full example):
80
159
  ```python
81
160
  from agentcore_rl_toolkit import AgentCoreRLApp
82
- from agentcore_rl_toolkit.frameworks.strands.vllm_model import vLLMModel
83
161
  from strands import Agent
162
+ from strands.models.openai import OpenAIModel
84
163
 
85
164
  app = AgentCoreRLApp()
86
165
  reward_fn = GSM8KReward() # user-defined reward function
@@ -89,24 +168,46 @@ reward_fn = GSM8KReward() # user-defined reward function
89
168
  def invoke_agent(payload: dict):
90
169
  base_url = payload["_rollout"]["base_url"]
91
170
  model_id = payload["_rollout"]["model_id"]
92
- model = vLLMModel(client_args={"api_key": "EMPTY", "base_url": base_url}, model_id=model_id)
171
+ model = OpenAIModel(client_args={"api_key": "EMPTY", "base_url": base_url}, model_id=model_id)
93
172
  agent = Agent(model=model, tools=[...], system_prompt="...")
94
173
 
95
174
  response = agent(payload.get("prompt"))
96
- rollout_data = model.get_token_data()
97
175
  rewards = reward_fn(response_text=response.message["content"][0]["text"], ground_truth=payload.get("answer"))
98
- return {"rollout_data": rollout_data, "rewards": rewards}
176
+ return {"rewards": rewards}
99
177
  ```
100
178
 
101
179
  **Key changes:**
102
180
  1. `BedrockAgentCoreApp` → `AgentCoreRLApp` (framework-agnostic)
103
- 2. `BedrockModel` → `vLLMModel` created inside the entrypoint with `base_url`/`model_id` from `_rollout` payload
181
+ 2. `BedrockModel` → `OpenAIModel` created inside the entrypoint with `base_url`/`model_id` from `_rollout` payload
104
182
  3. `@app.entrypoint` → `@app.rollout_entrypoint`
105
- 4. Use `model.get_token_data()` to collect token IDs directly (avoids retokenization)
106
- 5. Return `{"rollout_data": ..., "rewards": ...}` instead of text
183
+ 4. Return a dict instead of text (`rewards` key required for training)
184
+
185
+ > **Note:** The return value is flexible — any JSON-serializable dict works. This example returns rewards for training, but for evaluation you might return rewards, conversation history, or other artifacts. You can also persist raw data to S3 and run evaluation logic client-side.
107
186
 
108
187
  **Why create model and agent inside the entrypoint?** During RL training, the training engine can pass runtime configuration—such as inference server address, sampling parameters, and system prompt—via the `_rollout` payload, giving flexibility to accommodate different learning scenarios. This is safe because RL rollouts are single-invocation: the agent doesn't need persistent conversation history across requests, so there's no need to define model and agent as global variables.
109
188
 
189
+ ### Background: Token Capture for RL Training
190
+
191
+ > **Note:** This section is background knowledge — you don't need to configure any of this yourself. Token capture is managed by the training infrastructure.
192
+
193
+ RL for LLMs trains on token sequences, so trainers need the exact token IDs sampled by the model. But agents communicate via OpenAI-compatible APIs that return text, not tokens. Re-tokenizing that text back into IDs causes **retokenization drift** — the reconstructed IDs may differ from what the model actually generated, leading to off-policy updates that destabilize training. This drift has [three common sources](https://vllm.ai/blog/agent-lightning): (1) non-unique tokenization (e.g., `H`+`AVING` retokenizes as `HAV`+`ING`), (2) tool-call serialization changes (whitespace/formatting shifts during parsing and re-rendering), and (3) chat template misalignment across frameworks.
194
+
195
+ The solution is to capture token IDs directly from the inference server, avoiding retokenization entirely. [rllm-model-gateway](https://github.com/rllm-org/rllm/tree/main/rllm-model-gateway) does this as a transparent HTTP proxy between agents and the inference server:
196
+
197
+ ```
198
+ Agent ──► rllm-model-gateway ──► Inference Server (vLLM/SGLang)
199
+ │
200
+ └─► captures token IDs + logprobs, scoped by session
201
+ ```
202
+
203
+ The gateway intercepts OpenAI-compatible API responses and extracts token data directly from the server. Crucially, it scopes captured data by session ID — so when hundreds of concurrent agent sessions hit the same gateway, each rollout's token trace is correctly associated with its trajectory. Agents use a standard `OpenAIModel` and are completely unaware of the capture.
204
+
205
+ In practice, this is infrastructure managed by the training framework:
206
+ - **During training**: the training engine points `base_url` through the gateway automatically
207
+ - **During evaluation**: `base_url` points directly to any OpenAI-compatible endpoint (vLLM, SGLang, LiteLLM, etc.), or you can use `BedrockModel` via the Bedrock API — no gateway involved
208
+
209
+ The gateway is [available on PyPI](https://pypi.org/project/rllm-model-gateway/) (`pip install rllm-model-gateway`). See the [rllm-model-gateway repo](https://github.com/rllm-org/rllm/tree/main/rllm-model-gateway) for details.
210
+
110
211
  ## Client-Side: Invoking Agents and Collecting Results
111
212
 
112
213
  LLM agent rollouts are long-running and asynchronous — an agent may run for minutes or even hours as it reasons and makes tool calls. Both sides of this toolkit are designed around that constraint:
@@ -149,8 +250,8 @@ for f in futures:
149
250
 
150
251
  **How the future lifecycle works:**
151
252
  - **`client.invoke()`** sends the request to ACR and returns a `RolloutFuture` immediately — this means ACR has received the request and a background agent session is processing it.
152
- - **`future.result(timeout=...)`** blocks until the result appears in S3, polling with exponential backoff internally. It returns the complete rollout data (token IDs, rewards, etc.) once the agent finishes and writes to S3.
153
- - **Automatic session cleanup**: Once a result is fetched or a timeout is reached, the underlying ACR session is automatically cancelled — no manual cleanup needed.
253
+ - **`future.result(timeout=...)`** blocks until the result appears in S3, polling with exponential backoff internally. It returns the result (rewards, metrics, etc.) once the agent finishes and writes to S3.
254
+ - **Automatic session cleanup**: Once a result is fetched or a timeout is reached, the underlying ACR session is automatically cancelled to avoid wasteful idle time — no manual cleanup needed.
154
255
 
155
256
  ### Batch Evaluation (`run_batch()`)
156
257
 
@@ -207,10 +308,14 @@ The training architecture follows a **decoupled design** where agent rollouts an
207
308
  │ │ (e.g., veRL) │ │ (vLLM/SGLang) │ │
208
309
  │ └───────┬─────────────┘ └───────▲─────────────┘ │
209
310
  │ │ │ │
311
+ │ │ ┌───────┴─────────────┐ │
312
+ │ │ │ rllm-model-gateway │ │
313
+ │ │ │ (token capture) │ │
314
+ │ │ └───────▲─────────────┘ │
210
315
  └───────────────┼──────────────────────────┼─────────────────────┘
211
316
  │ 1. Submit N prompts │ ◄── ART Client-Side (1): RolloutClient
212
- │ to ACR │ 2. Model inference ◄── ART Agent-Side (2): vLLMModel
213
- ▼ │ calls from agents
317
+ │ to ACR │ 2. Model inference
318
+ ▼ │ via standard OpenAI API
214
319
  ┌────────────────────────────────────────────────────────────────┐
215
320
  │ AWS Bedrock AgentCore Runtime │
216
321
  │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
@@ -219,28 +324,34 @@ The training architecture follows a **decoupled design** where agent rollouts an
219
324
  │ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │
220
325
  │ │ │ │ │
221
326
  │ └──────────────┴───────────────────┘ │
222
- │ │ 3. Save rollouts + rewards │ ◄── ART Agent-Side (3): @rollout_entrypoint
327
+ │ │ 3. Save rewards to S3 │ ◄── ART Agent-Side (3): @rollout_entrypoint
223
328
  │ ▼ │
224
329
  │ ┌───────────────────┐ │
225
- │ │ S3 (rollouts) │ │
330
+ │ │ S3 (results) │ │
226
331
  │ └─────────┬─────────┘ │
227
332
  └─────────────────────────────┼──────────────────────────────────┘
228
333
  │ 4. Poll S3 HEAD for results ◄── ART Client-Side (4): RolloutFuture
229
334
  ▼
230
- Training Engine receives
231
- rollouts for policy update
335
+ Training Engine reads tokens
336
+ from gateway + rewards from S3
337
+ for policy update
232
338
  ```
233
339
 
234
340
  **Workflow:**
235
341
  1. **Prompt submission**: Training engine uses `RolloutClient` to submit N prompts to ACR — it injects rollout configs (`input_id`, `s3_bucket`, etc.) and handles rate limiting and concurrency, while ACR auto-scales N parallel agent sessions
236
- 2. **Agent execution**: Each agent session runs the `@rollout_entrypoint`, which launches the agent loop asynchronously (reporting `/ping` as busy) and calls the inference server via `vLLMModel` for model responses
237
- 3. **Rollout collection**: When the agent finishes, `@rollout_entrypoint` saves rollouts and rewards to S3 and reports `/ping` as idle so ACR can reclaim the session
238
- 4. **Policy update**: Training engine uses `RolloutFuture` to poll S3 for completed rollouts and updates the model
342
+ 2. **Agent execution**: Each agent session runs the `@rollout_entrypoint`, which launches the agent loop asynchronously (reporting `/ping` as busy) and calls the inference server via standard OpenAI-compatible API (through the gateway during training)
343
+ 3. **Result collection**: When the agent finishes, `@rollout_entrypoint` saves rewards to S3 and reports `/ping` as idle so ACR can reclaim the session
344
+ 4. **Policy update**: Training engine collects token data from the gateway and rewards from S3 to update the model
239
345
 
240
346
  This architecture enables parallel and highly efficient rollouts with secure execution during RL training. The decoupled design means training libraries only need the agent's container image to start training—agent code and dependencies stay completely separate from the training library.
241
347
 
242
348
  **Supported Training Libraries:**
243
- - To be announced.
349
+ - [rLLM](https://github.com/rllm-org/rllm) — supports multiple backends (veRL, Tinker, and more)
350
+ - [Math Agent](examples/strands_math_agent/): [Tinker](https://github.com/rllm-org/rllm/blob/main/examples/agentcore_math/train_agentcore_math_tinker.sh)
351
+
352
+ For a self-hosted Tinker-compatible training and sampling endpoint, see the
353
+ [SkyRL EC2 deployment example](src/agentcore_rl_toolkit/backends/tinker_api/skyrl/).
354
+ It uses SkyPilot to deploy Qwen3.5-4B on one P4d.
244
355
 
245
356
  ### Prepare Your Agent Container
246
357
 
@@ -281,12 +392,29 @@ chmod +x scripts/build_docker_image_and_push_to_ecr.sh
281
392
  --context=examples/strands_math_agent
282
393
  ```
283
394
 
395
+ ## Sandbox: Command Execution in Arbitrary Images
396
+
397
+ Coding-agent evaluation and RL training typically start from prebuilt environment images (repository checkout, dependencies, test runner) that are not HTTP agent servers. The sandbox SDK bridges them onto AgentCore Runtime: a tiny health shim (`agentcore-sandboxd`, built from [`sandboxd/`](./sandboxd/)) is added to the image to satisfy the ACR container contract, and commands run through ACR's native `InvokeAgentRuntimeCommand` API.
398
+
399
+ ```python
400
+ from agentcore_rl_toolkit.sandbox import SandboxClient
401
+
402
+ client = SandboxClient(runtime_arn="arn:aws:bedrock-agentcore:...:runtime/...")
403
+ with client.start() as sb:
404
+ result = sb.exec("cd /app && pytest -q", timeout=900)
405
+ print(result.exit_code, result.stdout)
406
+ ```
407
+
408
+ Failing commands and timeouts are results, not exceptions — exactly what reward functions need. See [`examples/sandbox_quickstart/`](./examples/sandbox_quickstart/) for the full walkthrough (build the shim binary, wrap and push an image, create a runtime, run commands).
409
+
284
410
  ## Contributing
285
411
 
286
412
  We welcome contributions!
287
413
 
288
414
  - **Adding examples**: Create a new folder under `examples/` with its own `pyproject.toml`
289
415
  - **Improving the core library**: See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup
416
+ - **Proposing significant features or architectural changes**: See the
417
+ [design document process](designs/README.md)
290
418
 
291
419
  For bug reports, feature requests, and pull request guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md).
292
420
 
@@ -1,31 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: agentcore-rl-toolkit
3
- Version: 0.1.2
4
- Summary: Toolkit for Seamlessly Enabling RL Training with Bedrock AgentCore.
5
- Project-URL: Homepage, https://github.com/awslabs/agentcore-rl-toolkit
6
- Author-email: Amazon Web Services - Labs <opensource@amazon.com>
7
- License-Expression: Apache-2.0
8
- License-File: LICENSE
9
- License-File: NOTICE
10
- Classifier: Development Status :: 3 - Alpha
11
- Classifier: License :: OSI Approved :: Apache Software License
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.10
14
- Classifier: Programming Language :: Python :: 3.11
15
- Classifier: Programming Language :: Python :: 3.12
16
- Classifier: Programming Language :: Python :: 3.13
17
- Requires-Python: >=3.10
18
- Requires-Dist: bedrock-agentcore-starter-toolkit>=0.2.0
19
- Requires-Dist: bedrock-agentcore>=1.0.3
20
- Requires-Dist: boto3>=1.40.55
21
- Requires-Dist: python-dotenv>=1.0.0
22
- Provides-Extra: dev
23
- Requires-Dist: mypy>=1.0; extra == 'dev'
24
- Requires-Dist: pre-commit>=3.0; extra == 'dev'
25
- Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
26
- Requires-Dist: pytest>=7.0; extra == 'dev'
27
- Description-Content-Type: text/markdown
28
-
29
1
 
30
2
  # AgentCore RL Toolkit (ART)
31
3
 
@@ -33,12 +5,12 @@ Toolkit to Seamlessly Enable RL Training on Any Agent with Bedrock AgentCore.
33
5
 
34
6
  ## Overview
35
7
 
36
- **AgentCore RL Toolkit (ART)** is an SDK that helps developers adapt their production LLM agents for online RL training with **AWS Bedrock AgentCore Runtime (ACR)**. It extends [bedrock-agentcore-sdk-python](https://github.com/aws/bedrock-agentcore-sdk-python/tree/main) so most of your production agent code can be directly reused.
8
+ **AgentCore RL Toolkit (ART)** is an SDK that helps developers adapt their production LLM agents for RL training with **AWS Bedrock AgentCore Runtime (ACR)**. It extends [bedrock-agentcore-sdk-python](https://github.com/aws/bedrock-agentcore-sdk-python/tree/main) so most of your production agent code can be directly reused.
37
9
 
38
10
  LLM agent rollouts are long-running — an agent may run for minutes or hours making tool calls. The toolkit manages this with an async-first design:
39
11
 
40
- - **Agent Adaptation** (`AgentCoreRLApp`, `vLLMModel`): Adapt your production agent for RL training inside ACR — the `@rollout_entrypoint` decorator runs your agent in the background with fire-and-forget semantics, collecting token-level data, computing rewards, and saving results to S3.
41
- - **Simplified Rollout Collection** (`RolloutClient`, `RolloutFuture`): Submit rollout requests and collect results asynchronously with a future-based API, built-in concurrency control, rate limiting, and S3 polling — for both training loops and batch evaluation.
12
+ - **Agent Adaptation** (`AgentCoreRLApp`, `@rollout_entrypoint`): A decorator swap turns your production agent into an async, fire-and-forget service — the agent runs in the background and saves results to S3. Return any JSON-serializable artifacts: rewards for RL training, evaluation metrics, conversation history, or custom data.
13
+ - **Rollout Collection** (`RolloutClient`, `RolloutFuture`): Submit requests and collect results asynchronously with a future-based API, built-in concurrency control, rate limiting, and S3 polling — for both training loops and batch evaluation.
42
14
 
43
15
  Both components use S3 as their data layer, but the complexity is fully abstracted — your code never reads from or writes to S3 directly.
44
16
 
@@ -68,11 +40,12 @@ While session routing is valuable for multi-turn production agents, RL rollouts
68
40
 
69
41
  ## Key Features
70
42
 
71
- - **Minimal code changes**: Adapt your production agent with a decorator swap (`@app.entrypoint` → `@app.rollout_entrypoint`) and model replacement — most of your agent code stays the same
72
- - **Token-accurate rollout data**: `vLLMModel` collects token IDs and logprobs directly from the inference server, avoiding retokenization issues that cause training instability
43
+ - **Minimal code changes**: Adapt your production agent with a decorator swap (`@app.entrypoint` → `@app.rollout_entrypoint`) — most of your agent code stays the same
44
+ - **No custom model wrappers**: Your agent uses standard framework models (e.g., `OpenAIModel`). Token capture for RL training is handled at the infrastructure layer, not in your agent code
73
45
  - **Async end-to-end**: Fire-and-forget server + future-based client — no long-lived TCP connections needed for long-running agent rollouts
74
46
  - **Simplified rollout collection**: `RolloutClient` manages concurrency, rate limiting, and S3 result polling out of the box for both training loops and batch evaluation
75
47
  - **Production parity**: Direct code reuse from production agents ensures training behavior matches real deployment
48
+ - **Sandbox on ACR** (`SandboxClient` + `agentcore-sandboxd`): Run shell commands in arbitrary Docker images (e.g. SWE-bench-style coding environments) as isolated AgentCore runtime sessions — no agent server required in the image
76
49
 
77
50
  ## Agent-Side: Adapting Your Agent for RL
78
51
 
@@ -107,8 +80,8 @@ if __name__ == "__main__":
107
80
  Starting from a deployment-ready agent like above, here are the changes needed for RL training (see [`rl_app.py`](examples/strands_math_agent/rl_app.py) for full example):
108
81
  ```python
109
82
  from agentcore_rl_toolkit import AgentCoreRLApp
110
- from agentcore_rl_toolkit.frameworks.strands.vllm_model import vLLMModel
111
83
  from strands import Agent
84
+ from strands.models.openai import OpenAIModel
112
85
 
113
86
  app = AgentCoreRLApp()
114
87
  reward_fn = GSM8KReward() # user-defined reward function
@@ -117,24 +90,46 @@ reward_fn = GSM8KReward() # user-defined reward function
117
90
  def invoke_agent(payload: dict):
118
91
  base_url = payload["_rollout"]["base_url"]
119
92
  model_id = payload["_rollout"]["model_id"]
120
- model = vLLMModel(client_args={"api_key": "EMPTY", "base_url": base_url}, model_id=model_id)
93
+ model = OpenAIModel(client_args={"api_key": "EMPTY", "base_url": base_url}, model_id=model_id)
121
94
  agent = Agent(model=model, tools=[...], system_prompt="...")
122
95
 
123
96
  response = agent(payload.get("prompt"))
124
- rollout_data = model.get_token_data()
125
97
  rewards = reward_fn(response_text=response.message["content"][0]["text"], ground_truth=payload.get("answer"))
126
- return {"rollout_data": rollout_data, "rewards": rewards}
98
+ return {"rewards": rewards}
127
99
  ```
128
100
 
129
101
  **Key changes:**
130
102
  1. `BedrockAgentCoreApp` → `AgentCoreRLApp` (framework-agnostic)
131
- 2. `BedrockModel` → `vLLMModel` created inside the entrypoint with `base_url`/`model_id` from `_rollout` payload
103
+ 2. `BedrockModel` → `OpenAIModel` created inside the entrypoint with `base_url`/`model_id` from `_rollout` payload
132
104
  3. `@app.entrypoint` → `@app.rollout_entrypoint`
133
- 4. Use `model.get_token_data()` to collect token IDs directly (avoids retokenization)
134
- 5. Return `{"rollout_data": ..., "rewards": ...}` instead of text
105
+ 4. Return a dict instead of text (`rewards` key required for training)
106
+
107
+ > **Note:** The return value is flexible — any JSON-serializable dict works. This example returns rewards for training, but for evaluation you might return rewards, conversation history, or other artifacts. You can also persist raw data to S3 and run evaluation logic client-side.
135
108
 
136
109
  **Why create model and agent inside the entrypoint?** During RL training, the training engine can pass runtime configuration—such as inference server address, sampling parameters, and system prompt—via the `_rollout` payload, giving flexibility to accommodate different learning scenarios. This is safe because RL rollouts are single-invocation: the agent doesn't need persistent conversation history across requests, so there's no need to define model and agent as global variables.
137
110
 
111
+ ### Background: Token Capture for RL Training
112
+
113
+ > **Note:** This section is background knowledge — you don't need to configure any of this yourself. Token capture is managed by the training infrastructure.
114
+
115
+ RL for LLMs trains on token sequences, so trainers need the exact token IDs sampled by the model. But agents communicate via OpenAI-compatible APIs that return text, not tokens. Re-tokenizing that text back into IDs causes **retokenization drift** — the reconstructed IDs may differ from what the model actually generated, leading to off-policy updates that destabilize training. This drift has [three common sources](https://vllm.ai/blog/agent-lightning): (1) non-unique tokenization (e.g., `H`+`AVING` retokenizes as `HAV`+`ING`), (2) tool-call serialization changes (whitespace/formatting shifts during parsing and re-rendering), and (3) chat template misalignment across frameworks.
116
+
117
+ The solution is to capture token IDs directly from the inference server, avoiding retokenization entirely. [rllm-model-gateway](https://github.com/rllm-org/rllm/tree/main/rllm-model-gateway) does this as a transparent HTTP proxy between agents and the inference server:
118
+
119
+ ```
120
+ Agent ──► rllm-model-gateway ──► Inference Server (vLLM/SGLang)
121
+ │
122
+ └─► captures token IDs + logprobs, scoped by session
123
+ ```
124
+
125
+ The gateway intercepts OpenAI-compatible API responses and extracts token data directly from the server. Crucially, it scopes captured data by session ID — so when hundreds of concurrent agent sessions hit the same gateway, each rollout's token trace is correctly associated with its trajectory. Agents use a standard `OpenAIModel` and are completely unaware of the capture.
126
+
127
+ In practice, this is infrastructure managed by the training framework:
128
+ - **During training**: the training engine points `base_url` through the gateway automatically
129
+ - **During evaluation**: `base_url` points directly to any OpenAI-compatible endpoint (vLLM, SGLang, LiteLLM, etc.), or you can use `BedrockModel` via the Bedrock API — no gateway involved
130
+
131
+ The gateway is [available on PyPI](https://pypi.org/project/rllm-model-gateway/) (`pip install rllm-model-gateway`). See the [rllm-model-gateway repo](https://github.com/rllm-org/rllm/tree/main/rllm-model-gateway) for details.
132
+
138
133
  ## Client-Side: Invoking Agents and Collecting Results
139
134
 
140
135
  LLM agent rollouts are long-running and asynchronous — an agent may run for minutes or even hours as it reasons and makes tool calls. Both sides of this toolkit are designed around that constraint:
@@ -177,8 +172,8 @@ for f in futures:
177
172
 
178
173
  **How the future lifecycle works:**
179
174
  - **`client.invoke()`** sends the request to ACR and returns a `RolloutFuture` immediately — this means ACR has received the request and a background agent session is processing it.
180
- - **`future.result(timeout=...)`** blocks until the result appears in S3, polling with exponential backoff internally. It returns the complete rollout data (token IDs, rewards, etc.) once the agent finishes and writes to S3.
181
- - **Automatic session cleanup**: Once a result is fetched or a timeout is reached, the underlying ACR session is automatically cancelled — no manual cleanup needed.
175
+ - **`future.result(timeout=...)`** blocks until the result appears in S3, polling with exponential backoff internally. It returns the result (rewards, metrics, etc.) once the agent finishes and writes to S3.
176
+ - **Automatic session cleanup**: Once a result is fetched or a timeout is reached, the underlying ACR session is automatically cancelled to avoid wasteful idle time — no manual cleanup needed.
182
177
 
183
178
  ### Batch Evaluation (`run_batch()`)
184
179
 
@@ -235,10 +230,14 @@ The training architecture follows a **decoupled design** where agent rollouts an
235
230
  │ │ (e.g., veRL) │ │ (vLLM/SGLang) │ │
236
231
  │ └───────┬─────────────┘ └───────▲─────────────┘ │
237
232
  │ │ │ │
233
+ │ │ ┌───────┴─────────────┐ │
234
+ │ │ │ rllm-model-gateway │ │
235
+ │ │ │ (token capture) │ │
236
+ │ │ └───────▲─────────────┘ │
238
237
  └───────────────┼──────────────────────────┼─────────────────────┘
239
238
  │ 1. Submit N prompts │ ◄── ART Client-Side (1): RolloutClient
240
- │ to ACR │ 2. Model inference ◄── ART Agent-Side (2): vLLMModel
241
- ▼ │ calls from agents
239
+ │ to ACR │ 2. Model inference
240
+ ▼ │ via standard OpenAI API
242
241
  ┌────────────────────────────────────────────────────────────────┐
243
242
  │ AWS Bedrock AgentCore Runtime │
244
243
  │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
@@ -247,28 +246,34 @@ The training architecture follows a **decoupled design** where agent rollouts an
247
246
  │ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │
248
247
  │ │ │ │ │
249
248
  │ └──────────────┴───────────────────┘ │
250
- │ │ 3. Save rollouts + rewards │ ◄── ART Agent-Side (3): @rollout_entrypoint
249
+ │ │ 3. Save rewards to S3 │ ◄── ART Agent-Side (3): @rollout_entrypoint
251
250
  │ ▼ │
252
251
  │ ┌───────────────────┐ │
253
- │ │ S3 (rollouts) │ │
252
+ │ │ S3 (results) │ │
254
253
  │ └─────────┬─────────┘ │
255
254
  └─────────────────────────────┼──────────────────────────────────┘
256
255
  │ 4. Poll S3 HEAD for results ◄── ART Client-Side (4): RolloutFuture
257
256
  ▼
258
- Training Engine receives
259
- rollouts for policy update
257
+ Training Engine reads tokens
258
+ from gateway + rewards from S3
259
+ for policy update
260
260
  ```
261
261
 
262
262
  **Workflow:**
263
263
  1. **Prompt submission**: Training engine uses `RolloutClient` to submit N prompts to ACR — it injects rollout configs (`input_id`, `s3_bucket`, etc.) and handles rate limiting and concurrency, while ACR auto-scales N parallel agent sessions
264
- 2. **Agent execution**: Each agent session runs the `@rollout_entrypoint`, which launches the agent loop asynchronously (reporting `/ping` as busy) and calls the inference server via `vLLMModel` for model responses
265
- 3. **Rollout collection**: When the agent finishes, `@rollout_entrypoint` saves rollouts and rewards to S3 and reports `/ping` as idle so ACR can reclaim the session
266
- 4. **Policy update**: Training engine uses `RolloutFuture` to poll S3 for completed rollouts and updates the model
264
+ 2. **Agent execution**: Each agent session runs the `@rollout_entrypoint`, which launches the agent loop asynchronously (reporting `/ping` as busy) and calls the inference server via standard OpenAI-compatible API (through the gateway during training)
265
+ 3. **Result collection**: When the agent finishes, `@rollout_entrypoint` saves rewards to S3 and reports `/ping` as idle so ACR can reclaim the session
266
+ 4. **Policy update**: Training engine collects token data from the gateway and rewards from S3 to update the model
267
267
 
268
268
  This architecture enables parallel and highly efficient rollouts with secure execution during RL training. The decoupled design means training libraries only need the agent's container image to start training—agent code and dependencies stay completely separate from the training library.
269
269
 
270
270
  **Supported Training Libraries:**
271
- - To be announced.
271
+ - [rLLM](https://github.com/rllm-org/rllm) — supports multiple backends (veRL, Tinker, and more)
272
+ - [Math Agent](examples/strands_math_agent/): [Tinker](https://github.com/rllm-org/rllm/blob/main/examples/agentcore_math/train_agentcore_math_tinker.sh)
273
+
274
+ For a self-hosted Tinker-compatible training and sampling endpoint, see the
275
+ [SkyRL EC2 deployment example](src/agentcore_rl_toolkit/backends/tinker_api/skyrl/).
276
+ It uses SkyPilot to deploy Qwen3.5-4B on one P4d.
272
277
 
273
278
  ### Prepare Your Agent Container
274
279
 
@@ -309,12 +314,29 @@ chmod +x scripts/build_docker_image_and_push_to_ecr.sh
309
314
  --context=examples/strands_math_agent
310
315
  ```
311
316
 
317
+ ## Sandbox: Command Execution in Arbitrary Images
318
+
319
+ Coding-agent evaluation and RL training typically start from prebuilt environment images (repository checkout, dependencies, test runner) that are not HTTP agent servers. The sandbox SDK bridges them onto AgentCore Runtime: a tiny health shim (`agentcore-sandboxd`, built from [`sandboxd/`](./sandboxd/)) is added to the image to satisfy the ACR container contract, and commands run through ACR's native `InvokeAgentRuntimeCommand` API.
320
+
321
+ ```python
322
+ from agentcore_rl_toolkit.sandbox import SandboxClient
323
+
324
+ client = SandboxClient(runtime_arn="arn:aws:bedrock-agentcore:...:runtime/...")
325
+ with client.start() as sb:
326
+ result = sb.exec("cd /app && pytest -q", timeout=900)
327
+ print(result.exit_code, result.stdout)
328
+ ```
329
+
330
+ Failing commands and timeouts are results, not exceptions — exactly what reward functions need. See [`examples/sandbox_quickstart/`](./examples/sandbox_quickstart/) for the full walkthrough (build the shim binary, wrap and push an image, create a runtime, run commands).
331
+
312
332
  ## Contributing
313
333
 
314
334
  We welcome contributions!
315
335
 
316
336
  - **Adding examples**: Create a new folder under `examples/` with its own `pyproject.toml`
317
337
  - **Improving the core library**: See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup
338
+ - **Proposing significant features or architectural changes**: See the
339
+ [design document process](designs/README.md)
318
340
 
319
341
  For bug reports, feature requests, and pull request guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md).
320
342