@aws/agentcore 1.0.0-preview.13 → 1.0.0-preview.14
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.
- package/README.md +31 -17
- package/dist/agent-inspector/index.css +1 -1
- package/dist/agent-inspector/index.js +90 -85
- package/dist/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap +966 -106
- package/dist/assets/agents/AGENTS.md +14 -0
- package/dist/assets/cdk/bin/cdk.ts +42 -20
- package/dist/assets/cdk/lib/cdk-stack.ts +19 -14
- package/dist/assets/cdk/test/cdk.test.ts +2 -1
- package/dist/assets/container/python/Dockerfile +4 -0
- package/dist/assets/python/a2a/strands/capabilities/memory/session.py +4 -1
- package/dist/assets/python/agui/strands/capabilities/memory/session.py +4 -1
- package/dist/assets/python/http/googleadk/base/mcp_client/client.py +7 -7
- package/dist/assets/python/http/googleadk/base/pyproject.toml +1 -1
- package/dist/assets/python/http/langchain_langgraph/base/mcp_client/client.py +10 -8
- package/dist/assets/python/http/langchain_langgraph/base/pyproject.toml +1 -1
- package/dist/assets/python/http/openaiagents/base/main.py +19 -9
- package/dist/assets/python/http/openaiagents/base/mcp_client/client.py +4 -4
- package/dist/assets/python/http/openaiagents/base/pyproject.toml +1 -1
- package/dist/assets/python/http/strands/base/main.py +438 -27
- package/dist/assets/python/http/strands/base/mcp_client/client.py +45 -5
- package/dist/assets/python/http/strands/base/model/load.py +3 -3
- package/dist/assets/python/http/strands/base/pyproject.toml +5 -2
- package/dist/assets/python/http/strands/base/skills/fetcher.py +279 -0
- package/dist/assets/python/http/strands/capabilities/execution-limits/hooks/execution_limits.py +54 -0
- package/dist/assets/python/http/strands/capabilities/memory/session.py +4 -1
- package/dist/cli/index.mjs +1274 -1088
- package/dist/lib/errors/types.d.ts +18 -0
- package/dist/lib/errors/types.d.ts.map +1 -1
- package/dist/lib/errors/types.js +28 -1
- package/dist/lib/errors/types.js.map +1 -1
- package/dist/lib/schemas/io/config-io.d.ts.map +1 -1
- package/dist/lib/schemas/io/config-io.js +0 -2
- package/dist/lib/schemas/io/config-io.js.map +1 -1
- package/dist/schema/constants.d.ts +20 -0
- package/dist/schema/constants.d.ts.map +1 -1
- package/dist/schema/constants.js +25 -1
- package/dist/schema/constants.js.map +1 -1
- package/dist/schema/schemas/agent-env.d.ts +35 -0
- package/dist/schema/schemas/agent-env.d.ts.map +1 -1
- package/dist/schema/schemas/agentcore-project.d.ts +184 -25
- package/dist/schema/schemas/agentcore-project.d.ts.map +1 -1
- package/dist/schema/schemas/agentcore-project.js +81 -31
- package/dist/schema/schemas/agentcore-project.js.map +1 -1
- package/dist/schema/schemas/auth.d.ts +175 -0
- package/dist/schema/schemas/auth.d.ts.map +1 -1
- package/dist/schema/schemas/auth.js +126 -3
- package/dist/schema/schemas/auth.js.map +1 -1
- package/dist/schema/schemas/deployed-state.d.ts +140 -46
- package/dist/schema/schemas/deployed-state.d.ts.map +1 -1
- package/dist/schema/schemas/deployed-state.js +39 -14
- package/dist/schema/schemas/deployed-state.js.map +1 -1
- package/dist/schema/schemas/mcp-defs.d.ts +2 -1
- package/dist/schema/schemas/mcp-defs.d.ts.map +1 -1
- package/dist/schema/schemas/mcp-defs.js +3 -2
- package/dist/schema/schemas/mcp-defs.js.map +1 -1
- package/dist/schema/schemas/mcp.d.ts +186 -0
- package/dist/schema/schemas/mcp.d.ts.map +1 -1
- package/dist/schema/schemas/mcp.js +479 -4
- package/dist/schema/schemas/mcp.js.map +1 -1
- package/dist/schema/schemas/primitives/ab-test.d.ts +0 -6
- package/dist/schema/schemas/primitives/ab-test.d.ts.map +1 -1
- package/dist/schema/schemas/primitives/ab-test.js +0 -2
- package/dist/schema/schemas/primitives/ab-test.js.map +1 -1
- package/dist/schema/schemas/primitives/harness.d.ts +209 -11
- package/dist/schema/schemas/primitives/harness.d.ts.map +1 -1
- package/dist/schema/schemas/primitives/harness.js +268 -21
- package/dist/schema/schemas/primitives/harness.js.map +1 -1
- package/dist/schema/schemas/primitives/index.d.ts +6 -8
- package/dist/schema/schemas/primitives/index.d.ts.map +1 -1
- package/dist/schema/schemas/primitives/index.js +6 -5
- package/dist/schema/schemas/primitives/index.js.map +1 -1
- package/dist/schema/schemas/primitives/knowledge-base.d.ts +104 -0
- package/dist/schema/schemas/primitives/knowledge-base.d.ts.map +1 -0
- package/dist/schema/schemas/primitives/knowledge-base.js +99 -0
- package/dist/schema/schemas/primitives/knowledge-base.js.map +1 -0
- package/dist/schema/schemas/primitives/online-eval-config.d.ts +20 -2
- package/dist/schema/schemas/primitives/online-eval-config.d.ts.map +1 -1
- package/dist/schema/schemas/primitives/online-eval-config.js +43 -5
- package/dist/schema/schemas/primitives/online-eval-config.js.map +1 -1
- package/dist/schema/schemas/primitives/policy.d.ts +26 -0
- package/dist/schema/schemas/primitives/policy.d.ts.map +1 -1
- package/dist/schema/schemas/primitives/policy.js +5 -1
- package/dist/schema/schemas/primitives/policy.js.map +1 -1
- package/npm-shrinkwrap.json +195 -330
- package/package.json +10 -8
- package/scripts/bundle.mjs +51 -0
- package/scripts/run-e2e-local.sh +40 -8
- package/dist/schema/schemas/primitives/http-gateway.d.ts +0 -21
- package/dist/schema/schemas/primitives/http-gateway.d.ts.map +0 -1
- package/dist/schema/schemas/primitives/http-gateway.js +0 -34
- package/dist/schema/schemas/primitives/http-gateway.js.map +0 -1
|
@@ -122,6 +122,19 @@ When modifying JSON config files:
|
|
|
122
122
|
4. Use CloudFormation-safe names (alphanumeric, start with letter)
|
|
123
123
|
5. Run `agentcore validate` to verify changes
|
|
124
124
|
|
|
125
|
+
## Harness Export
|
|
126
|
+
|
|
127
|
+
`agentcore export harness` converts a harness configuration into a deployable Strands Python agent under `app/<agentName>/`.
|
|
128
|
+
|
|
129
|
+
**After every export, you MUST read `app/<agentName>/EXPORT_NOTES.md` before proceeding.**
|
|
130
|
+
|
|
131
|
+
This file lists any manual follow-up items required before the agent will deploy or run correctly — missing files to create, IAM policies to add, or configuration steps the exporter could not automate. A clean export produces "No manual steps required." Complete every item in the file before running `agentcore deploy`.
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
agentcore export harness --name <harnessName> # generates app/<agentName>/EXPORT_NOTES.md
|
|
135
|
+
cat app/<agentName>/EXPORT_NOTES.md # read this before touching anything else
|
|
136
|
+
```
|
|
137
|
+
|
|
125
138
|
## CLI Commands
|
|
126
139
|
|
|
127
140
|
| Command | Description |
|
|
@@ -129,6 +142,7 @@ When modifying JSON config files:
|
|
|
129
142
|
| `agentcore create` | Create a new project |
|
|
130
143
|
| `agentcore add <resource>` | Add agent, memory, credential, gateway, evaluator, policy |
|
|
131
144
|
| `agentcore remove <resource>` | Remove a resource |
|
|
145
|
+
| `agentcore export harness` | Export a harness to a Strands runtime agent |
|
|
132
146
|
| `agentcore dev` | Run agent locally with hot-reload |
|
|
133
147
|
| `agentcore deploy` | Deploy to AWS |
|
|
134
148
|
| `agentcore status` | Show deployment status |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { AgentCoreStack } from '../lib/cdk-stack';
|
|
3
|
-
import { ConfigIO, type AwsDeploymentTarget } from '@aws/agentcore-cdk';
|
|
2
|
+
import { AgentCoreStack, type HarnessConfig } from '../lib/cdk-stack';
|
|
3
|
+
import { ConfigIO, HarnessSpecSchema, type AwsDeploymentTarget } from '@aws/agentcore-cdk';
|
|
4
4
|
import { App, type Environment } from 'aws-cdk-lib';
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
import * as fs from 'fs';
|
|
@@ -56,40 +56,61 @@ async function main() {
|
|
|
56
56
|
throw new Error('No deployment targets configured. Please define targets in agentcore/aws-targets.json');
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
// Read harness configs
|
|
59
|
+
// Read harness configs: the full validated spec drives the CFN resource; the
|
|
60
|
+
// role-scoped fields drive the IAM role + container build.
|
|
60
61
|
const projectRoot = path.resolve(configRoot, '..');
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
62
|
+
|
|
63
|
+
// Read non-S3 KB connector-config files and pass their parsed contents to the
|
|
64
|
+
// L3 verbatim. The L3 does not read files; it expects the parsed
|
|
65
|
+
// connectorParameters keyed by the data source's connectorConfigFile path.
|
|
66
|
+
const connectorParametersByFile: Record<string, Record<string, unknown>> = {};
|
|
67
|
+
for (const kb of specAny.knowledgeBases ?? []) {
|
|
68
|
+
for (const ds of kb.dataSources ?? []) {
|
|
69
|
+
if (ds.type !== 'S3' && ds.connectorConfigFile) {
|
|
70
|
+
const abs = path.resolve(projectRoot, ds.connectorConfigFile);
|
|
71
|
+
try {
|
|
72
|
+
connectorParametersByFile[ds.connectorConfigFile] = JSON.parse(fs.readFileSync(abs, 'utf-8'));
|
|
73
|
+
} catch (err) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Could not read connector config '${ds.connectorConfigFile}' for knowledge base '${kb.name}' at ${abs}: ${err instanceof Error ? err.message : err}`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Harness is preview-gated. The CLI bundle bakes the preview flag at build time and
|
|
83
|
+
// forwards it to this child process via AGENTCORE_PREVIEW (see toolkit-lib/wrapper.ts).
|
|
84
|
+
// This app is built separately and cannot see that build-time define, so it gates on the
|
|
85
|
+
// env var. Absent/anything-but-'1' defaults to off so a stale harnesses[] entry in a
|
|
86
|
+
// non-preview build never synthesizes an AWS::BedrockAgentCore::Harness resource.
|
|
87
|
+
const previewEnabled = process.env.AGENTCORE_PREVIEW === '1';
|
|
88
|
+
|
|
89
|
+
const harnessConfigs: HarnessConfig[] = [];
|
|
90
|
+
for (const entry of previewEnabled ? (specAny.harnesses ?? []) : []) {
|
|
76
91
|
const harnessDir = path.resolve(projectRoot, entry.path);
|
|
77
92
|
const harnessPath = path.resolve(harnessDir, 'harness.json');
|
|
78
93
|
try {
|
|
79
|
-
const harnessSpec = JSON.parse(fs.readFileSync(harnessPath, 'utf-8'));
|
|
94
|
+
const harnessSpec = HarnessSpecSchema.parse(JSON.parse(fs.readFileSync(harnessPath, 'utf-8')));
|
|
80
95
|
harnessConfigs.push({
|
|
81
96
|
name: entry.name,
|
|
82
97
|
executionRoleArn: harnessSpec.executionRoleArn,
|
|
83
|
-
|
|
98
|
+
// Only an `existing` memory ref carries a name to wire IAM against; managed memory is
|
|
99
|
+
// owned by the harness (no sibling) and disabled has none — both resolve to undefined.
|
|
100
|
+
memoryName: harnessSpec.memory?.mode === 'existing' ? harnessSpec.memory.name : undefined,
|
|
84
101
|
containerUri: harnessSpec.containerUri,
|
|
85
102
|
hasDockerfile: !!harnessSpec.dockerfile,
|
|
86
103
|
dockerfile: harnessSpec.dockerfile,
|
|
87
104
|
codeLocation: harnessSpec.dockerfile ? harnessDir : undefined,
|
|
88
105
|
tools: harnessSpec.tools,
|
|
106
|
+
skills: harnessSpec.skills,
|
|
89
107
|
apiKeyArn: harnessSpec.model?.apiKeyArn,
|
|
90
108
|
efsAccessPoints: harnessSpec.efsAccessPoints,
|
|
91
109
|
s3AccessPoints: harnessSpec.s3AccessPoints,
|
|
92
110
|
apiFormat: harnessSpec.model?.apiFormat,
|
|
111
|
+
// Full spec + dir drive the AWS::BedrockAgentCore::Harness CFN resource.
|
|
112
|
+
spec: harnessSpec,
|
|
113
|
+
harnessDir,
|
|
93
114
|
});
|
|
94
115
|
} catch (err) {
|
|
95
116
|
throw new Error(
|
|
@@ -156,6 +177,7 @@ async function main() {
|
|
|
156
177
|
spec,
|
|
157
178
|
mcpSpec,
|
|
158
179
|
credentials,
|
|
180
|
+
connectorParametersByFile,
|
|
159
181
|
harnesses: harnessConfigs.length > 0 ? harnessConfigs : undefined,
|
|
160
182
|
paymentSpec,
|
|
161
183
|
env,
|
|
@@ -6,24 +6,18 @@ import {
|
|
|
6
6
|
type AgentCoreProjectSpec,
|
|
7
7
|
type AgentCoreMcpSpec,
|
|
8
8
|
type CustomJWTAuthorizerConfig,
|
|
9
|
+
type HarnessDeploymentConfig,
|
|
9
10
|
} from '@aws/agentcore-cdk';
|
|
10
11
|
import { CfnOutput, Stack, type StackProps } from 'aws-cdk-lib';
|
|
11
12
|
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
12
13
|
import { Construct } from 'constructs';
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
dockerfile?: string;
|
|
21
|
-
codeLocation?: string;
|
|
22
|
-
tools?: { type: string; name: string }[];
|
|
23
|
-
apiKeyArn?: string;
|
|
24
|
-
efsAccessPoints?: { accessPointArn: string; mountPath: string }[];
|
|
25
|
-
s3AccessPoints?: { accessPointArn: string; mountPath: string }[];
|
|
26
|
-
}
|
|
15
|
+
/**
|
|
16
|
+
* Harness deployment config: role-scoped fields (for IAM role + container build)
|
|
17
|
+
* plus the full validated spec + its config directory so the L3 construct can
|
|
18
|
+
* synthesize the AWS::BedrockAgentCore::Harness resource.
|
|
19
|
+
*/
|
|
20
|
+
export type HarnessConfig = HarnessDeploymentConfig;
|
|
27
21
|
|
|
28
22
|
export interface PaymentConnectorSpec {
|
|
29
23
|
name: string;
|
|
@@ -59,6 +53,11 @@ export interface AgentCoreStackProps extends StackProps {
|
|
|
59
53
|
* Harness role configurations.
|
|
60
54
|
*/
|
|
61
55
|
harnesses?: HarnessConfig[];
|
|
56
|
+
/**
|
|
57
|
+
* Parsed connectorParameters for non-S3 KB data sources, keyed by
|
|
58
|
+
* connectorConfigFile path. Forwarded to AgentCoreApplication.
|
|
59
|
+
*/
|
|
60
|
+
connectorParametersByFile?: Record<string, Record<string, unknown>>;
|
|
62
61
|
/**
|
|
63
62
|
* Payment specifications with resolved credential provider ARNs.
|
|
64
63
|
*/
|
|
@@ -98,7 +97,7 @@ export class AgentCoreStack extends Stack {
|
|
|
98
97
|
constructor(scope: Construct, id: string, props: AgentCoreStackProps) {
|
|
99
98
|
super(scope, id, props);
|
|
100
99
|
|
|
101
|
-
const { spec, mcpSpec, credentials, harnesses, paymentSpec } = props;
|
|
100
|
+
const { spec, mcpSpec, credentials, harnesses, connectorParametersByFile, paymentSpec } = props;
|
|
102
101
|
|
|
103
102
|
// Create AgentCoreApplication with all agents and harness roles
|
|
104
103
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -106,6 +105,12 @@ export class AgentCoreStack extends Stack {
|
|
|
106
105
|
if (harnesses?.length) {
|
|
107
106
|
appProps.harnesses = harnesses;
|
|
108
107
|
}
|
|
108
|
+
if (connectorParametersByFile && Object.keys(connectorParametersByFile).length > 0) {
|
|
109
|
+
appProps.connectorParametersByFile = connectorParametersByFile;
|
|
110
|
+
}
|
|
111
|
+
if (credentials) {
|
|
112
|
+
appProps.credentials = credentials;
|
|
113
|
+
}
|
|
109
114
|
this.application = new AgentCoreApplication(this, 'Application', appProps as any);
|
|
110
115
|
|
|
111
116
|
// Create AgentCoreMcp if there are gateways configured
|
|
@@ -14,13 +14,14 @@ test('AgentCoreStack synthesizes with empty spec', () => {
|
|
|
14
14
|
credentials: [],
|
|
15
15
|
evaluators: [],
|
|
16
16
|
onlineEvalConfigs: [],
|
|
17
|
+
configBundles: [],
|
|
17
18
|
policyEngines: [],
|
|
18
19
|
payments: [],
|
|
19
|
-
configBundles: [],
|
|
20
20
|
agentCoreGateways: [],
|
|
21
21
|
mcpRuntimeTools: [],
|
|
22
22
|
unassignedTargets: [],
|
|
23
23
|
datasets: [],
|
|
24
|
+
knowledgeBases: [],
|
|
24
25
|
},
|
|
25
26
|
});
|
|
26
27
|
const template = Template.fromStack(stack);
|
|
@@ -24,8 +24,11 @@ def get_memory_session_manager(session_id: Optional[str], actor_id: str) -> Opti
|
|
|
24
24
|
{{#if (includes memoryProviders.[0].strategies "USER_PREFERENCE")}}
|
|
25
25
|
f"/users/{actor_id}/preferences": RetrievalConfig(top_k=3, relevance_score=0.5),
|
|
26
26
|
{{/if}}
|
|
27
|
+
{{#if (includes memoryProviders.[0].strategies "EPISODIC")}}
|
|
28
|
+
f"/episodes/{actor_id}/{session_id}": RetrievalConfig(top_k=5, relevance_score=0.5),
|
|
29
|
+
{{/if}}
|
|
27
30
|
{{#if (includes memoryProviders.[0].strategies "SUMMARIZATION")}}
|
|
28
|
-
f"/summaries/{actor_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
|
|
31
|
+
f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
|
|
29
32
|
{{/if}}
|
|
30
33
|
}
|
|
31
34
|
{{/if}}
|
|
@@ -24,8 +24,11 @@ def get_memory_session_manager(session_id: Optional[str], actor_id: str) -> Opti
|
|
|
24
24
|
{{#if (includes memoryProviders.[0].strategies "USER_PREFERENCE")}}
|
|
25
25
|
f"/users/{actor_id}/preferences": RetrievalConfig(top_k=3, relevance_score=0.5),
|
|
26
26
|
{{/if}}
|
|
27
|
+
{{#if (includes memoryProviders.[0].strategies "EPISODIC")}}
|
|
28
|
+
f"/episodes/{actor_id}/{session_id}": RetrievalConfig(top_k=5, relevance_score=0.5),
|
|
29
|
+
{{/if}}
|
|
27
30
|
{{#if (includes memoryProviders.[0].strategies "SUMMARIZATION")}}
|
|
28
|
-
f"/summaries/{actor_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
|
|
31
|
+
f"/summaries/{actor_id}/{session_id}": RetrievalConfig(top_k=3, relevance_score=0.5),
|
|
29
32
|
{{/if}}
|
|
30
33
|
}
|
|
31
34
|
{{/if}}
|
|
@@ -34,20 +34,20 @@ def get_all_gateway_mcp_toolsets() -> list[MCPToolset]:
|
|
|
34
34
|
{{#each gatewayProviders}}
|
|
35
35
|
url = os.environ.get("{{envVarName}}")
|
|
36
36
|
if url:
|
|
37
|
-
|
|
37
|
+
{{#if (eq authType "AWS_IAM")}}
|
|
38
38
|
session = create_aws_session()
|
|
39
39
|
auth = SigV4HTTPXAuth(session.get_credentials(), "bedrock-agentcore", session.region_name)
|
|
40
|
-
toolsets.append(MCPToolset(connection_params=StreamableHTTPConnectionParams(
|
|
40
|
+
toolsets.append(MCPToolset(tool_name_prefix="{{snakeCase name}}", connection_params=StreamableHTTPConnectionParams(
|
|
41
41
|
url=url,
|
|
42
42
|
httpx_client_factory=lambda **kwargs: httpx.AsyncClient(auth=auth, **kwargs)
|
|
43
43
|
)))
|
|
44
|
-
|
|
44
|
+
{{else if (eq authType "CUSTOM_JWT")}}
|
|
45
45
|
token = _get_bearer_token_{{snakeCase name}}()
|
|
46
46
|
headers = {"Authorization": f"Bearer {token}"} if token else None
|
|
47
|
-
toolsets.append(MCPToolset(connection_params=StreamableHTTPConnectionParams(url=url, headers=headers)))
|
|
48
|
-
|
|
49
|
-
toolsets.append(MCPToolset(connection_params=StreamableHTTPConnectionParams(url=url)))
|
|
50
|
-
|
|
47
|
+
toolsets.append(MCPToolset(tool_name_prefix="{{snakeCase name}}", connection_params=StreamableHTTPConnectionParams(url=url, headers=headers)))
|
|
48
|
+
{{else}}
|
|
49
|
+
toolsets.append(MCPToolset(tool_name_prefix="{{snakeCase name}}", connection_params=StreamableHTTPConnectionParams(url=url)))
|
|
50
|
+
{{/if}}
|
|
51
51
|
else:
|
|
52
52
|
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
|
|
53
53
|
{{/each}}
|
|
@@ -11,7 +11,7 @@ requires-python = ">=3.10"
|
|
|
11
11
|
dependencies = [
|
|
12
12
|
"opentelemetry-distro",
|
|
13
13
|
"opentelemetry-exporter-otlp",
|
|
14
|
-
"google-adk >= 1.
|
|
14
|
+
"google-adk >= 1.35.0, < 2.0.0",
|
|
15
15
|
"google-genai >= 1.0.0, < 2.0.0",
|
|
16
16
|
"bedrock-agentcore >= 1.0.3",
|
|
17
17
|
"botocore[crt] >= 1.35.0",
|
|
@@ -32,23 +32,25 @@ def get_all_gateway_mcp_client() -> MultiServerMCPClient | None:
|
|
|
32
32
|
{{#each gatewayProviders}}
|
|
33
33
|
url = os.environ.get("{{envVarName}}")
|
|
34
34
|
if url:
|
|
35
|
-
|
|
35
|
+
{{#if (eq authType "AWS_IAM")}}
|
|
36
36
|
session = create_aws_session()
|
|
37
37
|
auth = SigV4HTTPXAuth(session.get_credentials(), "bedrock-agentcore", session.region_name)
|
|
38
|
-
servers["{{name}}"] = {"transport": "streamable_http", "url": url, "auth": auth}
|
|
39
|
-
|
|
38
|
+
servers["{{snakeCase name}}"] = {"transport": "streamable_http", "url": url, "auth": auth}
|
|
39
|
+
{{else if (eq authType "CUSTOM_JWT")}}
|
|
40
40
|
token = _get_bearer_token_{{snakeCase name}}()
|
|
41
41
|
headers = {"Authorization": f"Bearer {token}"} if token else None
|
|
42
|
-
servers["{{name}}"] = {"transport": "streamable_http", "url": url, "headers": headers}
|
|
43
|
-
|
|
44
|
-
servers["{{name}}"] = {"transport": "streamable_http", "url": url}
|
|
45
|
-
|
|
42
|
+
servers["{{snakeCase name}}"] = {"transport": "streamable_http", "url": url, "headers": headers}
|
|
43
|
+
{{else}}
|
|
44
|
+
servers["{{snakeCase name}}"] = {"transport": "streamable_http", "url": url}
|
|
45
|
+
{{/if}}
|
|
46
46
|
else:
|
|
47
47
|
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
|
|
48
48
|
{{/each}}
|
|
49
49
|
if not servers:
|
|
50
50
|
return None
|
|
51
|
-
|
|
51
|
+
# tool_name_prefix namespaces each gateway's tools by server key so multiple
|
|
52
|
+
# gateways exposing the same tool (e.g. x_amz_bedrock_agentcore_search) don't collide.
|
|
53
|
+
return MultiServerMCPClient(servers, tool_name_prefix=True)
|
|
52
54
|
{{else}}
|
|
53
55
|
{{#if isVpc}}
|
|
54
56
|
# VPC mode: external MCP endpoints are not reachable without a NAT gateway.
|
|
@@ -13,7 +13,7 @@ dependencies = [
|
|
|
13
13
|
"opentelemetry-instrumentation-langchain >= 0.59.0",
|
|
14
14
|
"langgraph >= 1.0.2",
|
|
15
15
|
"mcp >= 1.19.0",
|
|
16
|
-
"langchain-mcp-adapters >= 0.
|
|
16
|
+
"langchain-mcp-adapters >= 0.2.0",
|
|
17
17
|
"langchain >= 1.0.3",
|
|
18
18
|
"bedrock-agentcore >= 1.8.0",
|
|
19
19
|
"botocore[crt] >= 1.35.0",
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{{#if needsOs}}
|
|
2
2
|
import os
|
|
3
3
|
{{/if}}
|
|
4
|
+
{{#if hasGateway}}
|
|
5
|
+
from contextlib import AsyncExitStack
|
|
6
|
+
{{/if}}
|
|
4
7
|
from agents import Agent, Runner, function_tool
|
|
5
8
|
from bedrock_agentcore.runtime import BedrockAgentCoreApp
|
|
6
9
|
from model.load import load_model
|
|
@@ -111,15 +114,22 @@ async def main(query):
|
|
|
111
114
|
try:
|
|
112
115
|
{{#if hasGateway}}
|
|
113
116
|
if mcp_servers:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
mcp_servers
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
# Connect every gateway server before the run; include_server_in_tool_names
|
|
118
|
+
# namespaces each server's tools so multiple gateways exposing the same tool
|
|
119
|
+
# (e.g. x_amz_bedrock_agentcore_search) don't collide.
|
|
120
|
+
async with AsyncExitStack() as stack:
|
|
121
|
+
for server in mcp_servers:
|
|
122
|
+
await stack.enter_async_context(server)
|
|
123
|
+
agent = Agent(
|
|
124
|
+
name="{{ name }}",
|
|
125
|
+
model="gpt-4.1",
|
|
126
|
+
instructions=INSTRUCTIONS,
|
|
127
|
+
mcp_servers=mcp_servers,
|
|
128
|
+
tools=tools,
|
|
129
|
+
mcp_config={"include_server_in_tool_names": True},
|
|
130
|
+
)
|
|
131
|
+
result = await Runner.run(agent, query)
|
|
132
|
+
return result
|
|
123
133
|
else:
|
|
124
134
|
agent = Agent(
|
|
125
135
|
name="{{ name }}",
|
|
@@ -33,20 +33,20 @@ def get_all_gateway_mcp_servers() -> list[MCPServerStreamableHttp]:
|
|
|
33
33
|
{{#each gatewayProviders}}
|
|
34
34
|
url = os.environ.get("{{envVarName}}")
|
|
35
35
|
if url:
|
|
36
|
-
|
|
36
|
+
{{#if (eq authType "AWS_IAM")}}
|
|
37
37
|
session = create_aws_session()
|
|
38
38
|
auth = SigV4HTTPXAuth(session.get_credentials(), "bedrock-agentcore", session.region_name)
|
|
39
39
|
servers.append(MCPServerStreamableHttp(
|
|
40
40
|
name="{{name}}",
|
|
41
41
|
params={"url": url, "httpx_client_factory": lambda **kwargs: httpx.AsyncClient(auth=auth, **kwargs)}
|
|
42
42
|
))
|
|
43
|
-
|
|
43
|
+
{{else if (eq authType "CUSTOM_JWT")}}
|
|
44
44
|
token = _get_bearer_token_{{snakeCase name}}()
|
|
45
45
|
headers = {"Authorization": f"Bearer {token}"} if token else {}
|
|
46
46
|
servers.append(MCPServerStreamableHttp(name="{{name}}", params={"url": url, "headers": headers}))
|
|
47
|
-
|
|
47
|
+
{{else}}
|
|
48
48
|
servers.append(MCPServerStreamableHttp(name="{{name}}", params={"url": url}))
|
|
49
|
-
|
|
49
|
+
{{/if}}
|
|
50
50
|
else:
|
|
51
51
|
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
|
|
52
52
|
{{/each}}
|
|
@@ -10,7 +10,7 @@ readme = "README.md"
|
|
|
10
10
|
requires-python = ">=3.10"
|
|
11
11
|
dependencies = [
|
|
12
12
|
"aws-opentelemetry-distro",
|
|
13
|
-
"openai-agents >= 0.
|
|
13
|
+
"openai-agents >= 0.16.0",
|
|
14
14
|
"bedrock-agentcore >= 1.8.0",
|
|
15
15
|
"botocore[crt] >= 1.35.0",
|
|
16
16
|
{{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
|