Shared libraries
Five libraries live in libs/. Each is an independent uv project with its own
pyproject.toml, and each is packaged as a Lambda layer by the SAM template.
| Library | Import prefix | Layer | Purpose |
|---|---|---|---|
|
|
Event models, the SQS publisher, the cached secrets helper, Sentry |
|
|
|
Strands agent services, Bedrock, MCP tools, model ids |
|
|
|
SQLAlchemy models, repositories, session management |
|
|
|
BigQuery client factory |
|
|
|
The HubSpot client and every HubSpot API call |
Who uses what
| Consumer | common | llm | data-layer | bigquery | pyb-hubspot |
|---|---|---|---|---|---|
enrichment-scraper |
✓ |
✓ |
✓ |
||
enrichment-scorer |
✓ |
✓ |
✓ |
✓ |
|
morpheus-hubspot |
✓ |
✓ |
✓ |
✓ |
|
email-agent |
✓ |
✓ |
✓ |
||
phone-agent |
✓ |
✓ |
✓ |
||
agentcore runtime |
✓ |
MorpheusCommonLayer is always first in a function’s layer list — it provides Sentry,
which every handler configures at cold start.
The AgentCore runtime depends on morpheus-llm as an editable path dependency
([tool.uv.sources] in agentcore/pyproject.toml), not as a layer, since it is a
container rather than a Lambda.
Design rules
- Libraries never read the environment
-
create_hubspot_mcp(),create_tavily_mcp(),create_bigquery_client(), andHubSpotSyncClient.from_*()all take credentials as explicit keyword arguments. The caller fetches them from its own secrets loader. This keeps credential provenance visible at the call site and makes the library testable without environment manipulation. - Libraries never open transactions
-
morpheus_data_layerrepositories require aSessionargument and never commit. The caller owns the transaction boundary viaget_session(). - One responsibility each
-
pyb_hubspotowns every HubSpot API call — no consumer importshubspot.*directly.morpheus_llmowns every Bedrock and Strands construction. That is what makes rate-limit handling, auth modes, and prompt caching changeable in one place. - Lazy imports where the dependency is heavy
-
morpheus_llm/init.pyuses PEP 562getattr, soimport morpheus_llm.utilsdoes not pull in Bedrock, Strands, orbedrock_agentcore. Consumers additionally defer imports inside@lru_cachefunctions so modules stay importable without the layer installed. - Cross-library dependencies are allowed, cross-unit imports are not
-
pyb_hubspotimportsmorpheus_common.events.modelsfor property mapping, andmorpheus_llm.utils.hubspotre-exportspyb_hubspot.auth.refresh_hubspot_access_token. Both are fine. What is prohibited isagentcore/,lambdas/, andlibs/importing each other’s application code.
Dependency management
cd libs/morpheus-llm
uv add <package> # updates pyproject.toml + uv.lock
uv pip compile pyproject.toml -o requirements.txt # the manifest SAM builds from
Never pip install or poetry. Each layer is built by SAM with
BuildMethod: python3.12 against the library’s requirements.txt, so an unexported
dependency will not be in the deployed layer.
Layer details, including size and retention: Lambda layers.
Tests
cd libs/morpheus-common && uv run pytest tests -v # event model validation
cd libs/morpheus-data-layer && uv run pytest tests -v # repositories (integration/ needs a DB)
cd libs/pyb-hubspot && uv run pytest tests -v # HubSpot helpers, mocked SDK
cd libs/morpheus-bigquery && uv run pytest tests -v # client factory
morpheus-llm has no test suite of its own; it is exercised through the functions that
use it.