diff --git a/src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap b/src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap index 7f08e15b7b..285e085d41 100644 --- a/src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap +++ b/src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap @@ -3917,7 +3917,7 @@ environment where BMA runs commands. The ACR has no model code. | \`otel/collector.yaml\` | The configuration of the CloudWatch agent. The agent gets the spans and logs of \`codex exec-server\`, puts the session ID on them, and sends them to X-Ray and CloudWatch Logs with the ACR role. To turn off observability, add \`DISABLE_ADOT_OBSERVABILITY\` with the value \`true\` to \`envVars\`. | | \`plugins/acr-report\` | A Codex plugin with the \`acr-report\` skill. The skill saves the Python version, the user ID, and the working directory in \`acr-report.txt\`. | | \`bma-acr-policy.json\` | Lets the ACR role call \`bedrock-mantle:RegisterEnvironment\` and \`bedrock-mantle:ConnectEnvironment\` on every Mantle project. To limit the role to your projects, change \`Resource\` to \`arn:aws:bedrock-mantle:::project/\`. | -| \`pyproject.toml\` | The Python dependencies. \`aws-opentelemetry-distro\` sends a span for each call from BMA and a child span for each step of the call, for example the state load or the exec-server start. \`bedrock-agentcore\` is the AgentCore SDK. The \`dev\` group has the dependencies of \`client.py\`, and the image does not install it. Each image build installs the latest Python and the latest releases. To pin them, run \`uv lock\` and keep \`uv.lock\` next to this file. | +| \`pyproject.toml\` | The Python dependencies. \`aws-opentelemetry-distro\` sends a span for each call from BMA and a child span for each step of the call, for example the state load or the exec-server start. \`bedrock-agentcore\` is the AgentCore SDK. The \`dev\` group has the dependencies of \`client.py\`, and the image does not install it. Each image build installs the latest Python and the latest releases. To pin them, run \`uv lock\` and keep \`uv.lock\` next to this file. \`requires-python\` sets only a minimum, 3.12, so that \`uv run client.py\` does not use an older system Python. | | \`client.py\` | A sample OpenAI SDK client. It creates a session in BMA, and BMA sends the session's commands to this ACR. | Do not change \`lifecycle/server.py\`. It must match the lifecycle calls that BMA makes. @@ -4933,6 +4933,7 @@ name = "{{ name }}" version = "0.1.0" description = "AgentCore Runtime environment for Bedrock Managed Agents" readme = "README.md" +requires-python = ">=3.12" dependencies = [ "aws-opentelemetry-distro", "bedrock-agentcore", diff --git a/src/assets/python/http/bma/base/README.md b/src/assets/python/http/bma/base/README.md index df09959dbe..931fad06bb 100644 --- a/src/assets/python/http/bma/base/README.md +++ b/src/assets/python/http/bma/base/README.md @@ -12,7 +12,7 @@ environment where BMA runs commands. The ACR has no model code. | `otel/collector.yaml` | The configuration of the CloudWatch agent. The agent gets the spans and logs of `codex exec-server`, puts the session ID on them, and sends them to X-Ray and CloudWatch Logs with the ACR role. To turn off observability, add `DISABLE_ADOT_OBSERVABILITY` with the value `true` to `envVars`. | | `plugins/acr-report` | A Codex plugin with the `acr-report` skill. The skill saves the Python version, the user ID, and the working directory in `acr-report.txt`. | | `bma-acr-policy.json` | Lets the ACR role call `bedrock-mantle:RegisterEnvironment` and `bedrock-mantle:ConnectEnvironment` on every Mantle project. To limit the role to your projects, change `Resource` to `arn:aws:bedrock-mantle:::project/`. | -| `pyproject.toml` | The Python dependencies. `aws-opentelemetry-distro` sends a span for each call from BMA and a child span for each step of the call, for example the state load or the exec-server start. `bedrock-agentcore` is the AgentCore SDK. The `dev` group has the dependencies of `client.py`, and the image does not install it. Each image build installs the latest Python and the latest releases. To pin them, run `uv lock` and keep `uv.lock` next to this file. | +| `pyproject.toml` | The Python dependencies. `aws-opentelemetry-distro` sends a span for each call from BMA and a child span for each step of the call, for example the state load or the exec-server start. `bedrock-agentcore` is the AgentCore SDK. The `dev` group has the dependencies of `client.py`, and the image does not install it. Each image build installs the latest Python and the latest releases. To pin them, run `uv lock` and keep `uv.lock` next to this file. `requires-python` sets only a minimum, 3.12, so that `uv run client.py` does not use an older system Python. | | `client.py` | A sample OpenAI SDK client. It creates a session in BMA, and BMA sends the session's commands to this ACR. | Do not change `lifecycle/server.py`. It must match the lifecycle calls that BMA makes. diff --git a/src/assets/python/http/bma/base/pyproject.toml b/src/assets/python/http/bma/base/pyproject.toml index 9bbb0ffa23..10a862ddd7 100644 --- a/src/assets/python/http/bma/base/pyproject.toml +++ b/src/assets/python/http/bma/base/pyproject.toml @@ -3,6 +3,7 @@ name = "{{ name }}" version = "0.1.0" description = "AgentCore Runtime environment for Bedrock Managed Agents" readme = "README.md" +requires-python = ">=3.12" dependencies = [ "aws-opentelemetry-distro", "bedrock-agentcore", diff --git a/src/cli/templates/__tests__/bma.test.ts b/src/cli/templates/__tests__/bma.test.ts index 26933d4ca3..17827fc832 100644 --- a/src/cli/templates/__tests__/bma.test.ts +++ b/src/cli/templates/__tests__/bma.test.ts @@ -183,11 +183,19 @@ describe('BmaRenderer', () => { expect(main).toContain('if not OBSERVABILITY_ENABLED or not self.runtime_session_id:\n return False\n'); }); - it('installs the latest Python and writes no Python version', () => { + it('installs the latest Python in the image and sets only a minimum for client.py', () => { const agentDir = join(outputDir, 'app', 'BmaEnv'); const dockerfile = readFileSync(join(agentDir, 'Dockerfile'), 'utf-8'); expect(dockerfile).toContain('RUN uv python install --default\n'); - for (const file of ['Dockerfile', 'pyproject.toml', 'client.py']) { + // The image installs Python before it copies pyproject.toml, so the minimum does not pin the image. + expect(dockerfile.indexOf('RUN uv python install --default')).toBeLessThan( + dockerfile.indexOf('COPY pyproject.toml') + ); + // Without a minimum, `uv run client.py` can pick the macOS system Python 3.9, which openai does not support. + const pyproject = readFileSync(join(agentDir, 'pyproject.toml'), 'utf-8'); + expect(pyproject).toContain('requires-python = ">=3.12"\n'); + expect(pyproject.replace('requires-python = ">=3.12"\n', '')).not.toMatch(/requires-python|python[\s-]*3\.\d+/i); + for (const file of ['Dockerfile', 'client.py']) { const content = readFileSync(join(agentDir, file), 'utf-8'); expect(content).not.toMatch(/requires-python|python[\s-]*3\.\d+|install 3\.\d+/i); }