feat: factbase-cloud integration — knowledge_agent subagent with M2M auth

This commit is contained in:
daniel
2026-05-15 23:32:23 -05:00
parent ed6577ccf9
commit 42dbdcde9e
2 changed files with 44 additions and 1 deletions

View File

@@ -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', '')

View File

@@ -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()}"},
))],
} }