Skip to content

Commit de2e9d3

Browse files
committed
chore(agentcore): simplify agent identity extraction and remove dead code
1 parent 3af48ff commit de2e9d3

3 files changed

Lines changed: 23 additions & 54 deletions

File tree

examples/integrations/agentcore/agents/langgraph-single-agent/langgraph_agent.py

Lines changed: 22 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33

44
from __future__ import annotations
55

6-
import base64
7-
import json
8-
import os
96
import logging
7+
import os
108

119
from ag_ui.core import RunAgentInput, RunErrorEvent
1210
from bedrock_agentcore.identity.auth import requires_access_token
@@ -17,6 +15,7 @@
1715
from langchain_mcp_adapters.client import MultiServerMCPClient
1816
from langgraph_checkpoint_aws import AgentCoreMemorySaver
1917

18+
from utils.auth import extract_user_id_from_context
2019
from utils.ssm import get_ssm_parameter
2120
from tools import query_data, AgentState, todo_tools
2221

@@ -31,45 +30,6 @@
3130
When asked about your tools, list them and explain what they do."""
3231

3332

34-
def decode_jwt_sub(authorization_header: str | None) -> str | None:
35-
if not authorization_header:
36-
return None
37-
38-
parts = authorization_header.strip().split()
39-
if len(parts) != 2 or parts[0].lower() != "bearer":
40-
return None
41-
42-
token_parts = parts[1].split(".")
43-
if len(token_parts) < 2:
44-
return None
45-
46-
try:
47-
payload = token_parts[1]
48-
payload += "=" * ((4 - len(payload) % 4) % 4)
49-
decoded = base64.urlsafe_b64decode(payload.encode("utf-8"))
50-
sub = json.loads(decoded).get("sub")
51-
return sub if isinstance(sub, str) and sub else None
52-
except Exception:
53-
return None
54-
55-
56-
def resolve_actor_id(
57-
input_data: RunAgentInput, authorization_header: str | None
58-
) -> str | None:
59-
forwarded_props = (
60-
input_data.forwarded_props
61-
if isinstance(input_data.forwarded_props, dict)
62-
else {}
63-
)
64-
65-
for key in ACTOR_ID_KEYS:
66-
value = forwarded_props.get(key)
67-
if isinstance(value, str) and value:
68-
return value
69-
70-
return decode_jwt_sub(authorization_header)
71-
72-
7333
@requires_access_token(
7434
provider_name=os.environ["GATEWAY_CREDENTIAL_PROVIDER_NAME"],
7535
auth_flow="M2M",
@@ -123,14 +83,26 @@ def _build_checkpointer() -> AgentCoreMemorySaver:
12383
region_name=os.environ.get("AWS_DEFAULT_REGION", "us-east-1"),
12484
)
12585

86+
12687
@app.entrypoint
12788
async def invocations(payload: dict, context: RequestContext):
12889
input_data = RunAgentInput.model_validate(payload)
129-
authorization_header = None
130-
if context.request_headers:
131-
authorization_header = context.request_headers.get("Authorization")
13290

133-
actor_id = resolve_actor_id(input_data, authorization_header)
91+
# Extract actor identity securely from the validated JWT token.
92+
try:
93+
actor_id = extract_user_id_from_context(context)
94+
except ValueError:
95+
# Fall back to forwarded props if JWT extraction fails (e.g. local dev).
96+
forwarded = (
97+
input_data.forwarded_props
98+
if isinstance(input_data.forwarded_props, dict)
99+
else {}
100+
)
101+
actor_id = next(
102+
(forwarded[k] for k in ACTOR_ID_KEYS if k in forwarded and forwarded[k]),
103+
None,
104+
)
105+
134106
if not actor_id:
135107
raise ValueError(
136108
"Missing actor identity. Provide forwardedProps.actor_id/user_id "
@@ -151,16 +123,16 @@ async def invocations(payload: dict, context: RequestContext):
151123
checkpointer=_build_checkpointer(),
152124
middleware=[CopilotKitMiddleware()],
153125
system_prompt=SYSTEM_PROMPT,
154-
state_schema=AgentState, # extends BaseAgentState with todos: list[Todo]
126+
state_schema=AgentState,
155127
)
156128

157-
request_agent = LangGraphAGUIAgent(
129+
agent = LangGraphAGUIAgent(
158130
name="LangGraphSingleAgent",
159131
description="LangGraph single agent exposed via AG-UI",
160132
graph=graph,
161133
config={"configurable": {"actor_id": actor_id}},
162134
)
163-
async for event in request_agent.run(input_data):
135+
async for event in agent.run(input_data):
164136
if event is not None:
165137
yield event.model_dump(mode="json", by_alias=True, exclude_none=True)
166138
except Exception as exc:
@@ -172,4 +144,4 @@ async def invocations(payload: dict, context: RequestContext):
172144

173145

174146
if __name__ == "__main__":
175-
app.run()
147+
app.run()

examples/integrations/agentcore/agents/strands-single-agent/strands_agent.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,6 @@ async def todos_state_from_args(ctx: ToolCallContext) -> dict:
135135
"enableAppMode": frontend_tool_behavior,
136136
"enableChatMode": frontend_tool_behavior,
137137
},
138-
# default_frontend_tool_behavior=ToolBehavior(
139-
# continue_after_frontend_call=False,
140-
# skip_messages_snapshot=False,
141-
# ),
142138
state_context_builder=state_context_builder,
143139
)
144140

examples/integrations/agentcore/infra-cdk/lambdas/copilotkit-runtime/package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)