feat: factbase-cloud integration — knowledge_agent subagent with M2M auth
This commit is contained in:
@@ -6,6 +6,9 @@ _DEFAULTS = {
|
|||||||
'/agent-claw/model-id': 'us.anthropic.claude-sonnet-4-6',
|
'/agent-claw/model-id': 'us.anthropic.claude-sonnet-4-6',
|
||||||
'/agent-claw/config/compaction_model_id': 'us.anthropic.claude-3-5-haiku-20241022-v1:0',
|
'/agent-claw/config/compaction_model_id': 'us.anthropic.claude-3-5-haiku-20241022-v1:0',
|
||||||
'/agent-claw/aws-mcp-url': 'https://aws-mcp.us-east-1.api.aws/mcp',
|
'/agent-claw/aws-mcp-url': 'https://aws-mcp.us-east-1.api.aws/mcp',
|
||||||
|
'/agent-claw/factbase-cloud/client-id': '',
|
||||||
|
'/agent-claw/factbase-cloud/client-secret': '',
|
||||||
|
'/agent-claw/factbase-cloud/mcp-url': '',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -13,7 +16,7 @@ def _load():
|
|||||||
ssm = boto3.client('ssm', region_name='us-east-1')
|
ssm = boto3.client('ssm', region_name='us-east-1')
|
||||||
names = list(_DEFAULTS.keys())
|
names = list(_DEFAULTS.keys())
|
||||||
try:
|
try:
|
||||||
resp = ssm.get_parameters(Names=names)
|
resp = ssm.get_parameters(Names=names, WithDecryption=True)
|
||||||
found = {p['Name']: p['Value'] for p in resp['Parameters']}
|
found = {p['Name']: p['Value'] for p in resp['Parameters']}
|
||||||
except Exception:
|
except Exception:
|
||||||
found = {}
|
found = {}
|
||||||
@@ -25,3 +28,6 @@ _params = _load()
|
|||||||
AGENT_MODEL_ID: str = _params['/agent-claw/model-id']
|
AGENT_MODEL_ID: str = _params['/agent-claw/model-id']
|
||||||
COMPACTION_MODEL_ID: str = _params['/agent-claw/config/compaction_model_id']
|
COMPACTION_MODEL_ID: str = _params['/agent-claw/config/compaction_model_id']
|
||||||
AWS_MCP_URL: str = _params['/agent-claw/aws-mcp-url']
|
AWS_MCP_URL: str = _params['/agent-claw/aws-mcp-url']
|
||||||
|
FACTBASE_CLOUD_CLIENT_ID: str = _params.get('/agent-claw/factbase-cloud/client-id', '')
|
||||||
|
FACTBASE_CLOUD_CLIENT_SECRET: str = _params.get('/agent-claw/factbase-cloud/client-secret', '')
|
||||||
|
FACTBASE_CLOUD_MCP_URL: str = _params.get('/agent-claw/factbase-cloud/mcp-url', '')
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ agent-claw Runtime 1 — main assistant agent.
|
|||||||
Entrypoint for AgentCore CodeZip deployment.
|
Entrypoint for AgentCore CodeZip deployment.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
from strands import Agent, tool
|
from strands import Agent, tool
|
||||||
from strands.models import BedrockModel
|
from strands.models import BedrockModel
|
||||||
from bedrock_agentcore.runtime import BedrockAgentCoreApp
|
from bedrock_agentcore.runtime import BedrockAgentCoreApp
|
||||||
@@ -88,12 +89,48 @@ except Exception as _e:
|
|||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
|
||||||
|
|
||||||
|
# ── factbase-cloud token cache ────────────────────────────────────────────
|
||||||
|
_fc_token: str = ''
|
||||||
|
_fc_token_expiry: float = 0.0
|
||||||
|
|
||||||
|
def _get_factbase_cloud_token() -> str:
|
||||||
|
"""Fetch/cache a Cognito M2M token for factbase-cloud. Thread-safe for Lambda."""
|
||||||
|
global _fc_token, _fc_token_expiry
|
||||||
|
if _fc_token and time.time() < _fc_token_expiry - 60:
|
||||||
|
return _fc_token
|
||||||
|
if not config.FACTBASE_CLOUD_CLIENT_ID or not config.FACTBASE_CLOUD_CLIENT_SECRET:
|
||||||
|
raise RuntimeError('factbase-cloud credentials not configured in SSM')
|
||||||
|
resp = httpx.post(
|
||||||
|
'https://factbase-cloud.auth.us-east-1.amazoncognito.com/oauth2/token',
|
||||||
|
data={
|
||||||
|
'grant_type': 'client_credentials',
|
||||||
|
'client_id': config.FACTBASE_CLOUD_CLIENT_ID,
|
||||||
|
'client_secret': config.FACTBASE_CLOUD_CLIENT_SECRET,
|
||||||
|
'scope': 'factbase-cloud/read factbase-cloud/write',
|
||||||
|
},
|
||||||
|
headers={'Content-Type': 'application/x-www-form-urlencoded'},
|
||||||
|
timeout=10,
|
||||||
|
)
|
||||||
|
resp.raise_for_status()
|
||||||
|
data = resp.json()
|
||||||
|
_fc_token = data['access_token']
|
||||||
|
_fc_token_expiry = time.time() + data.get('expires_in', 3600)
|
||||||
|
print(f'[main] factbase-cloud token refreshed, expires in {data.get("expires_in", 3600)}s')
|
||||||
|
return _fc_token
|
||||||
|
|
||||||
|
|
||||||
# ── Subagent loading ──────────────────────────────────────────────────────
|
# ── Subagent loading ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
from mcp.client.streamable_http import streamablehttp_client
|
||||||
|
|
||||||
TOOL_PRESETS = {
|
TOOL_PRESETS = {
|
||||||
"aws": lambda: [MCPClient(lambda: aws_iam_streamablehttp_client(config.AWS_MCP_URL, aws_service="aws-mcp"))],
|
"aws": lambda: [MCPClient(lambda: aws_iam_streamablehttp_client(config.AWS_MCP_URL, aws_service="aws-mcp"))],
|
||||||
"coding": lambda: [MCPClient(lambda: aws_iam_streamablehttp_client(config.AWS_MCP_URL, aws_service="aws-mcp")), run_code],
|
"coding": lambda: [MCPClient(lambda: aws_iam_streamablehttp_client(config.AWS_MCP_URL, aws_service="aws-mcp")), run_code],
|
||||||
"documents": lambda: [http_request, file_read],
|
"documents": lambda: [http_request, file_read],
|
||||||
|
"factbase": lambda: [MCPClient(lambda: streamablehttp_client(
|
||||||
|
url=config.FACTBASE_CLOUD_MCP_URL,
|
||||||
|
headers={"Authorization": f"Bearer {_get_factbase_cloud_token()}"},
|
||||||
|
))],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user