@aws/nx-plugin 1.0.0-rc.18 → 1.0.0-rc.19

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 (87) hide show
  1. package/package.json +1 -1
  2. package/src/py/agent/__snapshots__/generator.spec.ts.snap +15 -6
  3. package/src/py/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +201 -0
  4. package/src/py/agent/a2a-connection/files/agent-connection/app/{__targetAgentSnakeCase___client.py.template → __targetAgentSnakeCase___client_strands.py.template} +7 -5
  5. package/src/py/agent/a2a-connection/generator.js +6 -5
  6. package/src/py/agent/a2a-connection/generator.js.map +1 -1
  7. package/src/py/agent/files/http/main.py.template +2 -2
  8. package/src/py/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +197 -0
  9. package/src/py/agent/gateway-connection/files/agent-connection/app/{__gatewaySnakeCase___client.py.template → __gatewaySnakeCase___client_strands.py.template} +6 -6
  10. package/src/py/agent/gateway-connection/generator.js +5 -5
  11. package/src/py/agent/gateway-connection/generator.js.map +1 -1
  12. package/src/py/agent/generator.js +3 -0
  13. package/src/py/agent/generator.js.map +1 -1
  14. package/src/py/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +157 -79
  15. package/src/py/agent/mcp-connection/files/agent-connection/app/{__mcpServerSnakeCase___client.py.template → __mcpServerSnakeCase___client_strands.py.template} +7 -5
  16. package/src/py/agent/mcp-connection/generator.js +5 -5
  17. package/src/py/agent/mcp-connection/generator.js.map +1 -1
  18. package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +37 -3
  19. package/src/py/fast-api/files/app/__name__/main.py.template +4 -1
  20. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +13 -4
  21. package/src/smithy/project/__snapshots__/generator.spec.ts.snap +1 -0
  22. package/src/smithy/project/files/src/operations/echo.smithy.template +1 -0
  23. package/src/terraform/project/files/application/src/main.tf.template +6 -1
  24. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +35 -4
  25. package/src/trpc/backend/files/src/procedures/echo.ts.template +1 -1
  26. package/src/trpc/backend/files/src/schema/echo.ts.template +2 -2
  27. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +14 -5
  28. package/src/ts/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +256 -0
  29. package/src/ts/agent/a2a-connection/files/agent-connection/app/{__targetAgentKebabCase__-client.ts.template → __targetAgentKebabCase__-client-strands.ts.template} +5 -5
  30. package/src/ts/agent/a2a-connection/generator.js +3 -3
  31. package/src/ts/agent/a2a-connection/generator.js.map +1 -1
  32. package/src/ts/agent/files/http/router.ts.template +1 -1
  33. package/src/ts/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +220 -0
  34. package/src/ts/agent/gateway-connection/files/agent-connection/app/{__gatewayKebabCase__-client.ts.template → __gatewayKebabCase__-client-strands.ts.template} +5 -5
  35. package/src/ts/agent/gateway-connection/generator.js +3 -3
  36. package/src/ts/agent/gateway-connection/generator.js.map +1 -1
  37. package/src/ts/agent/generator.js +3 -0
  38. package/src/ts/agent/generator.js.map +1 -1
  39. package/src/ts/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +183 -110
  40. package/src/ts/agent/mcp-connection/files/agent-connection/app/{__mcpServerKebabCase__-client.ts.template → __mcpServerKebabCase__-client-strands.ts.template} +5 -5
  41. package/src/ts/agent/mcp-connection/generator.js +3 -3
  42. package/src/ts/agent/mcp-connection/generator.js.map +1 -1
  43. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +13 -4
  44. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +64 -24
  45. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +13 -4
  46. package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +9 -3
  47. package/src/utils/agent-connection/agent-connection.d.ts +50 -24
  48. package/src/utils/agent-connection/agent-connection.js +137 -45
  49. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  50. package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client-config.ts.template +93 -0
  51. package/src/utils/agent-connection/files/core-auth/agentcore-endpoints.ts.template +37 -0
  52. package/src/utils/agent-connection/files/core-auth/agentcore-fetch.ts.template +54 -0
  53. package/src/utils/agent-connection/files/core-gateway/agentcore-gateway-mcp-transport.ts.template +41 -0
  54. package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-transport.ts.template +70 -0
  55. package/src/utils/agent-connection/files/core-shared/agentcore-transport.ts.template +39 -0
  56. package/src/utils/agent-connection/files/core-strands/a2a/agentcore-a2a-client-strands.ts.template +61 -0
  57. package/src/utils/agent-connection/files/core-strands/gateway/agentcore-gateway-mcp-client-strands.ts.template +26 -0
  58. package/src/utils/agent-connection/files/core-strands/mcp/agentcore-mcp-client-strands.ts.template +27 -0
  59. package/src/utils/agent-connection/files/py-core-a2a/agentcore_a2a_client_config.py.template +43 -0
  60. package/src/utils/agent-connection/files/py-core-auth/agentcore_endpoints.py.template +47 -0
  61. package/src/utils/agent-connection/files/py-core-auth/auth/session.py.template +51 -0
  62. package/src/utils/agent-connection/files/py-core-gateway/agentcore_gateway_mcp_transport.py.template +28 -0
  63. package/src/utils/agent-connection/files/py-core-mcp/agentcore_mcp_transport.py.template +34 -0
  64. package/src/utils/agent-connection/files/py-core-shared/agentcore_transport.py.template +40 -0
  65. package/src/utils/agent-connection/files/py-core-strands/a2a/agentcore_a2a_client_strands.py.template +66 -0
  66. package/src/utils/agent-connection/files/py-core-strands/gateway/agentcore_gateway_mcp_client_strands.py.template +22 -0
  67. package/src/utils/agent-connection/files/py-core-strands/mcp/agentcore_mcp_client_strands.py.template +30 -0
  68. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.tf.template +7 -2
  69. package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +13 -4
  70. package/src/utils/api-constructs/files/cdk/core/api/http/http-api.ts.template +9 -0
  71. package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +23 -1
  72. package/src/utils/files/terraform/src/core/runtime-config/appconfig-deployment/appconfig-deployment.tf.template +9 -3
  73. package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +7 -2
  74. package/src/utils/identity-constructs/files/terraform/core/user-identity/add-callback-url/add-callback-url.tf.template +9 -3
  75. package/src/utils/rdb-constructs/files/terraform/app/dbs/__nameKebabCase__/__nameKebabCase__.tf.template +22 -8
  76. package/src/utils/rdb-constructs/files/terraform/core/rdb/aurora/aurora.tf.template +10 -4
  77. package/src/utils/website-constructs/files/terraform/core/static-website/static-website.tf.template +13 -4
  78. package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client.ts.template +0 -123
  79. package/src/utils/agent-connection/files/core-gateway/agentcore-gateway-mcp-client.ts.template +0 -78
  80. package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-client.ts.template +0 -128
  81. package/src/utils/agent-connection/files/py-core-a2a/agentcore_a2a_client.py.template +0 -120
  82. package/src/utils/agent-connection/files/py-core-gateway/agentcore_gateway_mcp_client.py.template +0 -78
  83. package/src/utils/agent-connection/files/py-core-mcp/agentcore_mcp_client.py.template +0 -89
  84. /package/src/utils/agent-connection/files/{core-runtime-config/model-errors.ts.template → core-strands/base/model-errors-strands.ts.template} +0 -0
  85. /package/src/utils/agent-connection/files/{core-runtime-config/with-session-id.ts.template → core-strands/base/with-session-id-strands.ts.template} +0 -0
  86. /package/src/utils/agent-connection/files/{py-core-runtime-config/model_errors.py.template → py-core-strands/base/model_errors_strands.py.template} +0 -0
  87. /package/src/utils/agent-connection/files/{py-core-runtime-config/with_session_id.py.template → py-core-strands/base/with_session_id_strands.py.template} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws/nx-plugin",
3
- "version": "1.0.0-rc.18",
3
+ "version": "1.0.0-rc.19",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/awslabs/nx-plugin-for-aws.git",
@@ -1108,14 +1108,19 @@ resource "null_resource" "docker_publish" {
1108
1108
  provisioner "local-exec" {
1109
1109
  command = <<-EOT
1110
1110
  # Get ECR login token
1111
- aws ecr get-login-password --region \${local.aws_region} | docker login --username AWS --password-stdin \${self.triggers.repository_url}
1111
+ aws ecr get-login-password --region "$AWS_REGION" | docker login --username AWS --password-stdin "$REPOSITORY_URL"
1112
1112
 
1113
1113
  # Tag the image
1114
- docker tag \${self.triggers.docker_image_tag} \${self.triggers.repository_url}:latest
1114
+ docker tag "$DOCKER_IMAGE_TAG" "$REPOSITORY_URL:latest"
1115
1115
 
1116
1116
  # Push the image
1117
- docker push \${self.triggers.repository_url}:latest
1117
+ docker push "$REPOSITORY_URL:latest"
1118
1118
  EOT
1119
+ environment = {
1120
+ AWS_REGION = local.aws_region
1121
+ REPOSITORY_URL = self.triggers.repository_url
1122
+ DOCKER_IMAGE_TAG = self.triggers.docker_image_tag
1123
+ }
1119
1124
  }
1120
1125
 
1121
1126
  depends_on = [aws_ecr_repository_policy.agent_core_ecr_policy]
@@ -1177,10 +1182,11 @@ resource "null_resource" "runtime_ready" {
1177
1182
  uv run --with boto3 python -c "
1178
1183
  import boto3
1179
1184
  import json
1185
+ import os
1180
1186
  import time
1181
1187
  import uuid
1182
1188
 
1183
- runtime_arn = '\${self.triggers.runtime_arn}'
1189
+ runtime_arn = os.environ['RUNTIME_ARN']
1184
1190
  client = boto3.client('bedrock-agentcore')
1185
1191
  initialize_request = json.dumps({
1186
1192
  'jsonrpc': '2.0',
@@ -1212,6 +1218,9 @@ while True:
1212
1218
  print(f'Runtime {runtime_arn} is serving MCP')
1213
1219
  "
1214
1220
  EOT
1221
+ environment = {
1222
+ RUNTIME_ARN = self.triggers.runtime_arn
1223
+ }
1215
1224
  }
1216
1225
  }
1217
1226
 
@@ -1285,7 +1294,7 @@ exports[`py#agent generator > should match snapshot for generated files > agent-
1285
1294
  import uvicorn
1286
1295
  from bedrock_agentcore.runtime.models import PingStatus
1287
1296
  from fastapi import Request
1288
- from pydantic import BaseModel
1297
+ from pydantic import BaseModel, Field
1289
1298
  from starlette.middleware.base import BaseHTTPMiddleware
1290
1299
  from proj_agent_connection import session_id_context, with_session_id
1291
1300
 
@@ -1303,7 +1312,7 @@ _agent = _agent_ctx.__enter__()
1303
1312
 
1304
1313
 
1305
1314
  class InvokeInput(BaseModel):
1306
- message: str
1315
+ message: str = Field(max_length=100000)
1307
1316
 
1308
1317
 
1309
1318
  class StreamChunk(BaseModel):
@@ -0,0 +1,201 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`py#agent#a2a-connection generator > should match snapshot for agent-connection core files > agentcore_a2a_client_config.py 1`] = `
4
+ "from collections.abc import Callable
5
+
6
+ import boto3
7
+ import httpx
8
+ from a2a.client import ClientConfig
9
+
10
+ from .agentcore_endpoints import a2a_url_from_arn, region_from_arn
11
+ from .auth.session import jwt_auth, plain_auth, sigv4_auth
12
+
13
+
14
+ def _config(url: str, auth: httpx.Auth) -> tuple[str, ClientConfig]:
15
+ httpx_client = httpx.AsyncClient(auth=auth, timeout=120)
16
+ return url, ClientConfig(httpx_client=httpx_client, streaming=False)
17
+
18
+
19
+ class AgentCoreA2aClientConfig:
20
+ """Factory for A2A client configs that connect to a Bedrock AgentCore
21
+ runtime. Each forwards the current async-context session via the AgentCore
22
+ session header. Framework-agnostic — wrap the result in a framework's
23
+ A2A client."""
24
+
25
+ @staticmethod
26
+ def with_iam_auth(agent_runtime_arn: str) -> tuple[str, ClientConfig]:
27
+ """SigV4-authenticated A2A client config for a Bedrock AgentCore runtime."""
28
+ region = region_from_arn(agent_runtime_arn)
29
+ credentials = boto3.Session(region_name=region).get_credentials()
30
+ return _config(
31
+ a2a_url_from_arn(agent_runtime_arn), sigv4_auth(credentials, region)
32
+ )
33
+
34
+ @staticmethod
35
+ def with_jwt_auth(
36
+ agent_runtime_arn: str, access_token_provider: Callable[[], str]
37
+ ) -> tuple[str, ClientConfig]:
38
+ """Bearer-authenticated A2A client config for a Bedrock AgentCore runtime."""
39
+ return _config(
40
+ a2a_url_from_arn(agent_runtime_arn), jwt_auth(access_token_provider)
41
+ )
42
+
43
+ @staticmethod
44
+ def without_auth(url: str) -> tuple[str, ClientConfig]:
45
+ """Plain-HTTP A2A client config — for local dev."""
46
+ return _config(url, plain_auth())
47
+ "
48
+ `;
49
+
50
+ exports[`py#agent#a2a-connection generator > should match snapshot for agent-connection core files > agentcore_a2a_client_strands.py 1`] = `
51
+ "from collections.abc import Callable
52
+
53
+ from strands.agent.a2a_agent import A2AAgent
54
+
55
+ from .agentcore_a2a_client_config import AgentCoreA2aClientConfig
56
+
57
+
58
+ def _build(config: tuple, *, name: str | None, description: str | None) -> A2AAgent:
59
+ url, client_config = config
60
+ kwargs: dict = {"endpoint": url, "client_config": client_config}
61
+ if name:
62
+ kwargs["name"] = name
63
+ if description:
64
+ kwargs["description"] = description
65
+ return A2AAgent(**kwargs)
66
+
67
+
68
+ class AgentCoreA2aClientStrands:
69
+ """Factory for Strands A2A clients that connect to an AgentCore runtime."""
70
+
71
+ @staticmethod
72
+ def with_iam_auth(
73
+ agent_runtime_arn: str,
74
+ *,
75
+ name: str | None = None,
76
+ description: str | None = None,
77
+ ) -> A2AAgent:
78
+ """SigV4-authenticated client for a Bedrock AgentCore runtime."""
79
+ return _build(
80
+ AgentCoreA2aClientConfig.with_iam_auth(agent_runtime_arn),
81
+ name=name,
82
+ description=description,
83
+ )
84
+
85
+ @staticmethod
86
+ def with_jwt_auth(
87
+ agent_runtime_arn: str,
88
+ access_token_provider: Callable[[], str],
89
+ *,
90
+ name: str | None = None,
91
+ description: str | None = None,
92
+ ) -> A2AAgent:
93
+ """Bearer-authenticated client for a Bedrock AgentCore runtime."""
94
+ return _build(
95
+ AgentCoreA2aClientConfig.with_jwt_auth(
96
+ agent_runtime_arn, access_token_provider
97
+ ),
98
+ name=name,
99
+ description=description,
100
+ )
101
+
102
+ @staticmethod
103
+ def without_auth(
104
+ url: str,
105
+ *,
106
+ name: str | None = None,
107
+ description: str | None = None,
108
+ ) -> A2AAgent:
109
+ """Plain-HTTP client — for local dev."""
110
+ return _build(
111
+ AgentCoreA2aClientConfig.without_auth(url),
112
+ name=name,
113
+ description=description,
114
+ )
115
+ "
116
+ `;
117
+
118
+ exports[`py#agent#a2a-connection generator > should match snapshot for agent-connection core files > remote_client_strands.py 1`] = `
119
+ "import os
120
+
121
+ from strands.agent.a2a_agent import A2AAgent
122
+
123
+ from test_agent_connection.core.agentcore_a2a_client_strands import (
124
+ AgentCoreA2aClientStrands,
125
+ )
126
+ from test_agent_connection.core.runtime_config import (
127
+ get_agentcore_runtime_config,
128
+ )
129
+
130
+
131
+ class RemoteClientStrands:
132
+ """Strands client for the Remote A2A agent."""
133
+
134
+ @staticmethod
135
+ def create() -> A2AAgent:
136
+ if os.environ.get("SERVE_LOCAL") == "true":
137
+ return AgentCoreA2aClientStrands.without_auth("http://localhost:9001/")
138
+ config = get_agentcore_runtime_config()
139
+ agent_runtime_arn = config.get("agentRuntimes", {}).get("Remote")
140
+ if not agent_runtime_arn:
141
+ raise RuntimeError(
142
+ "No connected agent runtime named 'Remote' found in runtime configuration."
143
+ )
144
+ return AgentCoreA2aClientStrands.with_iam_auth(agent_runtime_arn)
145
+ "
146
+ `;
147
+
148
+ exports[`py#agent#a2a-connection generator > should match snapshot for agent-connection core files > session.py 1`] = `
149
+ "from collections.abc import Callable
150
+
151
+ import httpx
152
+
153
+ from ..session_context import get_current_session_id
154
+ from .sigv4 import SigV4HTTPXAuth
155
+
156
+ SESSION_HEADER = "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id"
157
+
158
+
159
+ class SessionHeaderAuth(httpx.Auth):
160
+ """Stamps the AgentCore session header from the current async context,
161
+ then delegates to an optional inner auth (e.g. SigV4)."""
162
+
163
+ requires_request_body = True
164
+ requires_response_body = True
165
+
166
+ def __init__(self, inner: httpx.Auth | None = None):
167
+ self._inner = inner
168
+
169
+ def auth_flow(self, request: httpx.Request): # type: ignore[override]
170
+ sid = get_current_session_id()
171
+ if sid:
172
+ request.headers[SESSION_HEADER] = sid
173
+ if self._inner is None:
174
+ yield request
175
+ return
176
+ yield from self._inner.auth_flow(request)
177
+
178
+
179
+ def sigv4_auth(
180
+ credentials, region: str, service: str = "bedrock-agentcore"
181
+ ) -> httpx.Auth:
182
+ """Session-forwarding SigV4 auth (per-request, body-aware)."""
183
+ return SessionHeaderAuth(SigV4HTTPXAuth(credentials, service, region))
184
+
185
+
186
+ def jwt_auth(access_token_provider: Callable[[], str]) -> httpx.Auth:
187
+ """Session-forwarding bearer-token auth."""
188
+
189
+ class _Bearer(httpx.Auth):
190
+ def auth_flow(self, request: httpx.Request):
191
+ request.headers["Authorization"] = f"Bearer {access_token_provider()}"
192
+ yield request
193
+
194
+ return SessionHeaderAuth(_Bearer())
195
+
196
+
197
+ def plain_auth() -> httpx.Auth:
198
+ """Session-forwarding plain auth — for local dev."""
199
+ return SessionHeaderAuth()
200
+ "
201
+ `;
@@ -2,19 +2,21 @@ import os
2
2
 
3
3
  from strands.agent.a2a_agent import A2AAgent
4
4
 
5
- from <%- agentConnectionModuleName %>.core.agentcore_a2a_client import AgentCoreA2aClient
5
+ from <%- agentConnectionModuleName %>.core.agentcore_a2a_client_strands import (
6
+ AgentCoreA2aClientStrands,
7
+ )
6
8
  from <%- agentConnectionModuleName %>.core.runtime_config import (
7
9
  get_agentcore_runtime_config,
8
10
  )
9
11
 
10
12
 
11
- class <%- targetAgentClassName %>Client:
12
- """Client for the <%- targetAgentClassName %> A2A agent."""
13
+ class <%- targetAgentClassName %>ClientStrands:
14
+ """Strands client for the <%- targetAgentClassName %> A2A agent."""
13
15
 
14
16
  @staticmethod
15
17
  def create() -> A2AAgent:
16
18
  if os.environ.get("SERVE_LOCAL") == "true":
17
- return AgentCoreA2aClient.without_auth(
19
+ return AgentCoreA2aClientStrands.without_auth(
18
20
  "http://localhost:<%- targetAgentPort %>/"
19
21
  )
20
22
  config = get_agentcore_runtime_config()
@@ -25,4 +27,4 @@ class <%- targetAgentClassName %>Client:
25
27
  raise RuntimeError(
26
28
  "No connected agent runtime named '<%- targetAgentClassName %>' found in runtime configuration."
27
29
  )
28
- return AgentCoreA2aClient.with_iam_auth(agent_runtime_arn)
30
+ return AgentCoreA2aClientStrands.with_iam_auth(agent_runtime_arn)
@@ -38,12 +38,13 @@ const pyAgentA2aConnectionGenerator = async (tree, options) => {
38
38
  // 1. Ensure the shared Python agent-connection project exists + has the
39
39
  // A2A core client and its shared SigV4 auth helper.
40
40
  await (0, agent_connection_1.ensurePythonAgentConnectionProject)(tree);
41
- (0, agent_connection_1.addPythonCoreClient)(tree, 'auth');
42
- (0, agent_connection_1.addPythonCoreClient)(tree, 'a2a');
41
+ await (0, agent_connection_1.addPythonCoreClient)(tree, 'a2a');
43
42
  const agentConnectionProjectDir = (0, agent_connection_1.getPythonAgentConnectionProjectDir)(tree);
44
43
  const agentConnectionModuleName = (0, agent_connection_1.getPythonAgentConnectionModuleName)(tree);
45
44
  const agentConnectionPackageName = (0, agent_connection_1.getPythonAgentConnectionPackageName)(tree);
46
- // Python deps required by the A2A core client + shared auth helper.
45
+ // Layer 0/1 deps for the A2A client config + shared auth helper, plus the
46
+ // Strands A2A extra the framework's A2A client needs (the base strands-agents
47
+ // dependency is added by addPythonCoreClient).
47
48
  (0, py_1.addDependenciesToPyProjectToml)(tree, agentConnectionProjectDir, [
48
49
  'boto3',
49
50
  'httpx',
@@ -64,12 +65,12 @@ const pyAgentA2aConnectionGenerator = async (tree, options) => {
64
65
  }
65
66
  // Add re-export to module __init__.py
66
67
  const moduleInitPath = (0, devkit_1.joinPathFragments)(agentConnectionProjectDir, agentConnectionModuleName, '__init__.py');
67
- await (0, agent_connection_1.addPythonReExport)(tree, moduleInitPath, `.app.${targetAgentSnakeCase}_client`, `${targetAgentClassName}Client`);
68
+ await (0, agent_connection_1.addPythonReExport)(tree, moduleInitPath, `.app.${targetAgentSnakeCase}_client_strands`, `${targetAgentClassName}ClientStrands`);
68
69
  // 3. Transform agent.py to add the A2A client import + wrap it as a tool
69
70
  const agentSourceDir = (0, devkit_1.joinPathFragments)(sourceProject.root, agentComponent.path ?? 'src');
70
71
  const agentFilePath = (0, devkit_1.joinPathFragments)(agentSourceDir, 'agent.py');
71
72
  if (tree.exists(agentFilePath)) {
72
- const clientClassName = `${targetAgentClassName}Client`;
73
+ const clientClassName = `${targetAgentClassName}ClientStrands`;
73
74
  const clientVarName = targetAgentSnakeCase;
74
75
  const toolName = `ask_${targetAgentSnakeCase}`;
75
76
  await addImportToAgentFile(tree, agentFilePath, agentConnectionModuleName, clientClassName);
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../../packages/nx-plugin/src/py/agent/a2a-connection/generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../../packages/nx-plugin/src/py/agent/a2a-connection/generator.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,uCAQoB;AACpB,uFAO0D;AAC1D,4CAI4B;AAC5B,kDAA6D;AAC7D,oDAAyE;AACzE,gDAAiD;AACjD,0CAK2B;AAC3B,0CAG2B;AAG3B,qDAAqD;AACrD,MAAM,EAAE,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,oBAAoB,OAAO,EAAE,CAAC;AAEjD,QAAA,sCAAsC,GACjD,IAAA,qBAAgB,EAAC,UAAU,CAAC,CAAC;AAExB,MAAM,6BAA6B,GAAG,KAAK,EAChD,IAAU,EACV,OAA4C,EAChB,EAAE;IAC9B,MAAM,aAAa,GAAG,IAAA,wCAAmC,EACvD,IAAI,EACJ,OAAO,CAAC,aAAa,CACtB,CAAC;IACF,MAAM,aAAa,GAAG,IAAA,wCAAmC,EACvD,IAAI,EACJ,OAAO,CAAC,aAAa,CACtB,CAAC;IAEF,MAAM,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAC/C,MAAM,oBAAoB,GAAG,OAAO,CAAC,eAAe,CAAC;IAErD,IAAI,CAAC,cAAc,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CACb,2FAA2F,CAC5F,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,oBAAoB,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CACb,iBAAiB,oBAAoB,CAAC,IAAI,cAAc,oBAAoB,CAAC,QAAQ,IAAI,MAAM,wDAAwD,CACxJ,CAAC;IACJ,CAAC;IAED,IACE,oBAAoB,CAAC,IAAI;QACzB,oBAAoB,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,KAAK,EACjD,CAAC;QACD,MAAM,IAAI,KAAK,CACb,yEAAyE,oBAAoB,CAAC,IAAI,WAAW,oBAAoB,CAAC,IAAI,mBAAmB,CAC1J,CAAC;IACJ,CAAC;IAED,MAAM,wBAAwB,GAAG,oBAAoB,CAAC,IAAI,IAAI,OAAO,CAAC;IACtE,MAAM,oBAAoB,GAAG,oBAAoB,CAAC,EAAY,CAAC;IAC/D,MAAM,oBAAoB,GAAG,IAAA,iBAAS,EAAC,oBAAoB,CAAC,CAAC;IAC7D,MAAM,eAAe,GAAG,oBAAoB,CAAC,IAAI,IAAI,IAAI,CAAC;IAE1D,wEAAwE;IACxE,uDAAuD;IACvD,MAAM,IAAA,qDAAkC,EAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,IAAA,sCAAmB,EAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAEvC,MAAM,yBAAyB,GAAG,IAAA,qDAAkC,EAAC,IAAI,CAAC,CAAC;IAC3E,MAAM,yBAAyB,GAAG,IAAA,qDAAkC,EAAC,IAAI,CAAC,CAAC;IAC3E,MAAM,0BAA0B,GAAG,IAAA,sDAAmC,EAAC,IAAI,CAAC,CAAC;IAE7E,0EAA0E;IAC1E,8EAA8E;IAC9E,+CAA+C;IAC/C,IAAA,mCAA8B,EAAC,IAAI,EAAE,yBAAyB,EAAE;QAC9D,OAAO;QACP,OAAO;QACP,qBAAqB;KACtB,CAAC,CAAC;IAEH,iFAAiF;IACjF,MAAM,MAAM,GAAG,IAAA,0BAAiB,EAC9B,yBAAyB,EACzB,yBAAyB,EACzB,KAAK,CACN,CAAC;IACF,IAAA,sBAAa,EACX,IAAI,EACJ,IAAA,0BAAiB,EAAC,SAAS,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,CAAC,EAChE,MAAM,EACN;QACE,oBAAoB;QACpB,oBAAoB;QACpB,eAAe;QACf,yBAAyB;KAC1B,EACD,EAAE,iBAAiB,EAAE,0BAAiB,CAAC,YAAY,EAAE,CACtD,CAAC;IAEF,gCAAgC;IAChC,MAAM,WAAW,GAAG,IAAA,0BAAiB,EAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7D,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,sCAAsC;IACtC,MAAM,cAAc,GAAG,IAAA,0BAAiB,EACtC,yBAAyB,EACzB,yBAAyB,EACzB,aAAa,CACd,CAAC;IACF,MAAM,IAAA,oCAAiB,EACrB,IAAI,EACJ,cAAc,EACd,QAAQ,oBAAoB,iBAAiB,EAC7C,GAAG,oBAAoB,eAAe,CACvC,CAAC;IAEF,yEAAyE;IACzE,MAAM,cAAc,GAAG,IAAA,0BAAiB,EACtC,aAAa,CAAC,IAAI,EAClB,cAAc,CAAC,IAAI,IAAI,KAAK,CAC7B,CAAC;IACF,MAAM,aAAa,GAAG,IAAA,0BAAiB,EAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IAEpE,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,MAAM,eAAe,GAAG,GAAG,oBAAoB,eAAe,CAAC;QAC/D,MAAM,aAAa,GAAG,oBAAoB,CAAC;QAC3C,MAAM,QAAQ,GAAG,OAAO,oBAAoB,EAAE,CAAC;QAE/C,MAAM,oBAAoB,CACxB,IAAI,EACJ,aAAa,EACb,yBAAyB,EACzB,eAAe,CAChB,CAAC;QACF,MAAM,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;QACpD,MAAM,uBAAuB,CAC3B,IAAI,EACJ,aAAa,EACb,eAAe,EACf,aAAa,EACb,QAAQ,EACR,oBAAoB,CACrB,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,IAAA,sCAAiC,EAC/B,IAAI,EACJ,aAAa,CAAC,IAAI,EAClB,0BAA0B,CAC3B,CAAC;IAEF,0EAA0E;IAC1E,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,IAAI,OAAO,CAAC;IACjD,MAAM,oBAAoB,GAAG,GAAG,SAAS,cAAc,CAAC;IACxD,MAAM,0BAA0B,GAAG,GAAG,wBAAwB,cAAc,CAAC;IAE7E,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC,oBAAoB,CAAC,EAAE,CAAC;QAClD,IAAA,sCAAiC,EAAC,aAAa,EAAE,oBAAoB,EAAE;YACrE,QAAQ,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC;YAC9B,MAAM,EAAE,0BAA0B;SACnC,CAAC,CAAC;QACH,IAAA,mCAA0B,EAAC,IAAI,EAAE,aAAa,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,IAAA,yCAA+B,EAAC,IAAI,EAAE;QAC1C,8CAAsC;KACvC,CAAC,CAAC;IAEH,MAAM,IAAA,6BAAoB,EAAC,IAAI,CAAC,CAAC;IACjC,OAAO,GAAG,EAAE;QACV,IAAA,4BAAmB,EAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC;AACJ,CAAC,CAAC;AA3JW,QAAA,6BAA6B,iCA2JxC;AAEF;;;;GAIG;AACH,MAAM,oBAAoB,GAAG,KAAK,EAChC,IAAU,EACV,QAAgB,EAChB,yBAAiC,EACjC,eAAuB,EACR,EAAE;IACjB,MAAM,IAAA,iCAA2B,EAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC;IACvE,MAAM,IAAA,iCAA2B,EAC/B,IAAI,EACJ,QAAQ,EACR,CAAC,eAAe,CAAC,EACjB,yBAAyB,CAC1B,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,cAAc,GAAG,KAAK,EAC1B,IAAU,EACV,QAAgB,EAChB,QAAgB,EACD,EAAE;IACjB,MAAM,IAAA,iBAAW,EACf,IAAI,EACJ,QAAQ,EACR,EAAE,CAAC;;2BAEoB,QAAQ;;iBAElB,QAAQ;;iDAEwB,QAAQ;;EAEvD,CAAC,CACA,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,uBAAuB,GAAG,KAAK,EACnC,IAAU,EACV,QAAgB,EAChB,eAAuB,EACvB,aAAqB,EACrB,QAAgB,EAChB,oBAA4B,EACb,EAAE;IACjB,IAAI,MAAM,IAAA,iBAAW,EAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,eAAe,WAAW,CAAC,CAAC,EAAE,CAAC;QAC3E,OAAO;IACT,CAAC;IAED,mEAAmE;IACnE,oEAAoE;IACpE,sEAAsE;IACtE,MAAM,SAAS,GAAG,GAAG,aAAa,MAAM,eAAe;;;UAG/C,QAAQ;+CAC6B,oBAAoB;qBAC9C,aAAa;CACjC,CAAC;IAEA,kEAAkE;IAClE,yEAAyE;IACzE,yCAAyC;IACzC,MAAM,IAAA,iBAAW,EACf,IAAI,EACJ,QAAQ,EACR,EAAE,CAAC;;;4BAGqB,eAAe;;MAErC,SAAS;YACH,CAAC,CACV,CAAC;AACJ,CAAC,CAAC;AAEF,kBAAe,qCAA6B,CAAC"}
@@ -3,7 +3,7 @@ import uuid
3
3
  import uvicorn
4
4
  from bedrock_agentcore.runtime.models import PingStatus
5
5
  from fastapi import Request
6
- from pydantic import BaseModel
6
+ from pydantic import BaseModel, Field
7
7
  from starlette.middleware.base import BaseHTTPMiddleware
8
8
  from <%- agentConnectionModuleName %> import session_id_context, with_session_id
9
9
 
@@ -21,7 +21,7 @@ _agent = _agent_ctx.__enter__()
21
21
 
22
22
 
23
23
  class InvokeInput(BaseModel):
24
- message: str
24
+ message: str = Field(max_length=100000)
25
25
 
26
26
 
27
27
  class StreamChunk(BaseModel):
@@ -0,0 +1,197 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`py#agent#gateway-connection generator > should match snapshot for agent-connection core files > agentcore_gateway_mcp_client_strands.py 1`] = `
4
+ "from strands.tools.mcp.mcp_client import MCPClient
5
+
6
+ from .agentcore_gateway_mcp_transport import AgentCoreGatewayMCPTransport
7
+
8
+
9
+ class AgentCoreGatewayMCPClientStrands:
10
+ """Factory for Strands MCP clients that connect to an AgentCore Gateway."""
11
+
12
+ @staticmethod
13
+ def with_iam_auth(
14
+ gateway_url: str,
15
+ region: str | None = None,
16
+ ) -> MCPClient:
17
+ """Create a gateway MCP client authenticated with IAM SigV4."""
18
+ return MCPClient(
19
+ AgentCoreGatewayMCPTransport.with_iam_auth(gateway_url, region)
20
+ )
21
+
22
+ @staticmethod
23
+ def without_auth(gateway_url: str) -> MCPClient:
24
+ """Plain-HTTP gateway client, for the local gateway started by serve-local."""
25
+ return MCPClient(AgentCoreGatewayMCPTransport.without_auth(gateway_url))
26
+ "
27
+ `;
28
+
29
+ exports[`py#agent#gateway-connection generator > should match snapshot for agent-connection core files > agentcore_gateway_mcp_transport.py 1`] = `
30
+ "from .agentcore_endpoints import region_from_gateway_url
31
+ from .agentcore_transport import (
32
+ TransportFactory,
33
+ no_auth_transport,
34
+ sigv4_transport,
35
+ )
36
+
37
+
38
+ class AgentCoreGatewayMCPTransport:
39
+ """Factory for MCP transport factories that connect to an AgentCore Gateway.
40
+ Forwards the current async-context session via the AgentCore session header,
41
+ which the gateway propagates to downstream MCP server targets.
42
+ """
43
+
44
+ @staticmethod
45
+ def with_iam_auth(
46
+ gateway_url: str,
47
+ region: str | None = None,
48
+ ) -> TransportFactory:
49
+ """Create a gateway MCP transport authenticated with IAM SigV4."""
50
+ return sigv4_transport(
51
+ gateway_url, region or region_from_gateway_url(gateway_url)
52
+ )
53
+
54
+ @staticmethod
55
+ def without_auth(gateway_url: str) -> TransportFactory:
56
+ """Plain-HTTP gateway transport, for the local gateway started by serve-local."""
57
+ return no_auth_transport(gateway_url)
58
+ "
59
+ `;
60
+
61
+ exports[`py#agent#gateway-connection generator > should match snapshot for agent-connection core files > agentcore_transport.py 1`] = `
62
+ "from collections.abc import Callable
63
+ from typing import Any
64
+
65
+ import boto3
66
+
67
+ from mcp.client.streamable_http import streamablehttp_client
68
+
69
+ from .auth.session import jwt_auth, plain_auth, sigv4_auth
70
+
71
+ # Agent frameworks wrap a transport *factory* — a no-arg callable returning a
72
+ # streamable-HTTP transport context manager. Typed as \`\`Any\`\` so this layer
73
+ # stays free of any framework-specific transport type.
74
+ TransportFactory = Callable[[], Any]
75
+
76
+
77
+ def _factory(url: str, auth) -> TransportFactory:
78
+ return lambda: streamablehttp_client(
79
+ url,
80
+ auth=auth,
81
+ timeout=120,
82
+ terminate_on_close=False,
83
+ )
84
+
85
+
86
+ def sigv4_transport(url: str, region: str) -> TransportFactory:
87
+ """SigV4-signed transport factory for a resolved AgentCore endpoint."""
88
+ credentials = boto3.Session(region_name=region).get_credentials()
89
+ return _factory(url, sigv4_auth(credentials, region))
90
+
91
+
92
+ def jwt_transport(
93
+ url: str, access_token_provider: Callable[[], str]
94
+ ) -> TransportFactory:
95
+ """Bearer-token transport factory for a resolved AgentCore endpoint."""
96
+ return _factory(url, jwt_auth(access_token_provider))
97
+
98
+
99
+ def no_auth_transport(url: str) -> TransportFactory:
100
+ """Plain-HTTP transport factory — for local dev."""
101
+ return _factory(url, plain_auth())
102
+ "
103
+ `;
104
+
105
+ exports[`py#agent#gateway-connection generator > should match snapshot for agent-connection core files > my_gateway_client_strands.py 1`] = `
106
+ "import os
107
+
108
+ from strands.tools.mcp.mcp_client import MCPClient
109
+
110
+ from proj_agent_connection.core.agentcore_gateway_mcp_client_strands import (
111
+ AgentCoreGatewayMCPClientStrands,
112
+ )
113
+ from proj_agent_connection.core.runtime_config import (
114
+ get_agentcore_runtime_config,
115
+ )
116
+
117
+
118
+ class MyGatewayClientStrands:
119
+ """Strands client for the MyGateway AgentCore Gateway.
120
+
121
+ Deployed: a SigV4-signed MCP client pointing at the gateway URL.
122
+ Local (\`\`SERVE_LOCAL=true\`\`): a plain-HTTP client pointing at the local
123
+ gateway started by the gateway project's serve-local target. The local
124
+ gateway aggregates every attached MCP server but does not evaluate
125
+ Cedar policies.
126
+ """
127
+
128
+ @staticmethod
129
+ def create() -> MCPClient:
130
+ if os.environ.get("SERVE_LOCAL") == "true":
131
+ return AgentCoreGatewayMCPClientStrands.without_auth(
132
+ gateway_url="http://localhost:8100/mcp"
133
+ )
134
+ config = get_agentcore_runtime_config()
135
+ gateway_url = config.get("gateways", {}).get("MyGateway")
136
+ if not gateway_url:
137
+ raise RuntimeError(
138
+ "No connected gateway named 'MyGateway' found in runtime configuration."
139
+ )
140
+ return AgentCoreGatewayMCPClientStrands.with_iam_auth(gateway_url=gateway_url)
141
+ "
142
+ `;
143
+
144
+ exports[`py#agent#gateway-connection generator > should match snapshot for agent-connection core files > session.py 1`] = `
145
+ "from collections.abc import Callable
146
+
147
+ import httpx
148
+
149
+ from ..session_context import get_current_session_id
150
+ from .sigv4 import SigV4HTTPXAuth
151
+
152
+ SESSION_HEADER = "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id"
153
+
154
+
155
+ class SessionHeaderAuth(httpx.Auth):
156
+ """Stamps the AgentCore session header from the current async context,
157
+ then delegates to an optional inner auth (e.g. SigV4)."""
158
+
159
+ requires_request_body = True
160
+ requires_response_body = True
161
+
162
+ def __init__(self, inner: httpx.Auth | None = None):
163
+ self._inner = inner
164
+
165
+ def auth_flow(self, request: httpx.Request): # type: ignore[override]
166
+ sid = get_current_session_id()
167
+ if sid:
168
+ request.headers[SESSION_HEADER] = sid
169
+ if self._inner is None:
170
+ yield request
171
+ return
172
+ yield from self._inner.auth_flow(request)
173
+
174
+
175
+ def sigv4_auth(
176
+ credentials, region: str, service: str = "bedrock-agentcore"
177
+ ) -> httpx.Auth:
178
+ """Session-forwarding SigV4 auth (per-request, body-aware)."""
179
+ return SessionHeaderAuth(SigV4HTTPXAuth(credentials, service, region))
180
+
181
+
182
+ def jwt_auth(access_token_provider: Callable[[], str]) -> httpx.Auth:
183
+ """Session-forwarding bearer-token auth."""
184
+
185
+ class _Bearer(httpx.Auth):
186
+ def auth_flow(self, request: httpx.Request):
187
+ request.headers["Authorization"] = f"Bearer {access_token_provider()}"
188
+ yield request
189
+
190
+ return SessionHeaderAuth(_Bearer())
191
+
192
+
193
+ def plain_auth() -> httpx.Auth:
194
+ """Session-forwarding plain auth — for local dev."""
195
+ return SessionHeaderAuth()
196
+ "
197
+ `;
@@ -2,16 +2,16 @@ import os
2
2
 
3
3
  from strands.tools.mcp.mcp_client import MCPClient
4
4
 
5
- from <%- agentConnectionModuleName %>.core.agentcore_gateway_mcp_client import (
6
- AgentCoreGatewayMCPClient,
5
+ from <%- agentConnectionModuleName %>.core.agentcore_gateway_mcp_client_strands import (
6
+ AgentCoreGatewayMCPClientStrands,
7
7
  )
8
8
  from <%- agentConnectionModuleName %>.core.runtime_config import (
9
9
  get_agentcore_runtime_config,
10
10
  )
11
11
 
12
12
 
13
- class <%- gatewayClassName %>Client:
14
- """Client for the <%- gatewayClassName %> AgentCore Gateway.
13
+ class <%- gatewayClassName %>ClientStrands:
14
+ """Strands client for the <%- gatewayClassName %> AgentCore Gateway.
15
15
 
16
16
  Deployed: a SigV4-signed MCP client pointing at the gateway URL.
17
17
  Local (``SERVE_LOCAL=true``): a plain-HTTP client pointing at the local
@@ -23,7 +23,7 @@ class <%- gatewayClassName %>Client:
23
23
  @staticmethod
24
24
  def create() -> MCPClient:
25
25
  if os.environ.get("SERVE_LOCAL") == "true":
26
- return AgentCoreGatewayMCPClient.without_auth(
26
+ return AgentCoreGatewayMCPClientStrands.without_auth(
27
27
  gateway_url="http://localhost:<%- gatewayPort %>/mcp"
28
28
  )
29
29
  config = get_agentcore_runtime_config()
@@ -32,4 +32,4 @@ class <%- gatewayClassName %>Client:
32
32
  raise RuntimeError(
33
33
  "No connected gateway named '<%- gatewayClassName %>' found in runtime configuration."
34
34
  )
35
- return AgentCoreGatewayMCPClient.with_iam_auth(gateway_url=gateway_url)
35
+ return AgentCoreGatewayMCPClientStrands.with_iam_auth(gateway_url=gateway_url)
@@ -38,16 +38,16 @@ const pyAgentGatewayConnectionGenerator = async (tree, options) => {
38
38
  const gatewayServeTargetName = `${gatewayKebabCase}-serve`;
39
39
  const gatewayServeLocalTargetName = `${gatewayKebabCase}-serve-local`;
40
40
  await (0, agent_connection_1.ensurePythonAgentConnectionProject)(tree);
41
- (0, agent_connection_1.addPythonCoreClient)(tree, 'auth');
42
- (0, agent_connection_1.addPythonCoreClient)(tree, 'gateway');
41
+ await (0, agent_connection_1.addPythonCoreClient)(tree, 'gateway');
43
42
  const agentConnectionProjectDir = (0, agent_connection_1.getPythonAgentConnectionProjectDir)(tree);
44
43
  const agentConnectionModuleName = (0, agent_connection_1.getPythonAgentConnectionModuleName)(tree);
45
44
  const agentConnectionPackageName = (0, agent_connection_1.getPythonAgentConnectionPackageName)(tree);
45
+ // Layer 0/1 deps for the MCP transport + signed httpx auth. The framework's
46
+ // own dependency (strands-agents) is added by addPythonCoreClient.
46
47
  (0, py_1.addDependenciesToPyProjectToml)(tree, agentConnectionProjectDir, [
47
48
  'boto3',
48
49
  'httpx',
49
50
  'mcp',
50
- 'strands-agents',
51
51
  ]);
52
52
  const appDir = (0, devkit_1.joinPathFragments)(agentConnectionProjectDir, agentConnectionModuleName, 'app');
53
53
  // Local mode points at the gateway project's local gateway port.
@@ -62,11 +62,11 @@ const pyAgentGatewayConnectionGenerator = async (tree, options) => {
62
62
  tree.write(appInitPath, '');
63
63
  }
64
64
  const moduleInitPath = (0, devkit_1.joinPathFragments)(agentConnectionProjectDir, agentConnectionModuleName, '__init__.py');
65
- await (0, agent_connection_1.addPythonReExport)(tree, moduleInitPath, `.app.${gatewaySnakeCase}_client`, `${gatewayClassName}Client`);
65
+ await (0, agent_connection_1.addPythonReExport)(tree, moduleInitPath, `.app.${gatewaySnakeCase}_client_strands`, `${gatewayClassName}ClientStrands`);
66
66
  const agentSourceDir = (0, devkit_1.joinPathFragments)(sourceProject.root, agentComponent.path ?? 'src');
67
67
  const agentFilePath = (0, devkit_1.joinPathFragments)(agentSourceDir, 'agent.py');
68
68
  if (tree.exists(agentFilePath)) {
69
- const clientClassName = `${gatewayClassName}Client`;
69
+ const clientClassName = `${gatewayClassName}ClientStrands`;
70
70
  const clientVarName = gatewaySnakeCase;
71
71
  await (0, ast_1.addPythonDestructuredImport)(tree, agentFilePath, [clientClassName], agentConnectionModuleName);
72
72
  await (0, agent_connection_1.addPythonClientToAgent)(tree, agentFilePath, clientClassName, clientVarName);