Build, define, and manage DynamoDB models and client code using Prismarine, the model-driven DynamoDB ORM for EasySAM and Python. Always use this skill when creating Prismarine clusters, defining @c.model or @c.index decorators, configuring resources.yaml prismarine settings, handling TypedDict or Pydantic modelling modes, or performing CRUD database operations via prismarine_client.
71
86%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
This skill provides guidelines and patterns for using Prismarine, a model-driven DynamoDB ORM for EasySAM and Python applications.
models.py:
Define Prismarine models inside a file explicitly named models.py (e.g., common/myobject/models.py). Do NOT define models in __init__.py.prefix:
The prefix passed to Cluster('MyPrefix') in models.py must start with the master prefix defined in resources.yaml (e.g., if resources.yaml prefix is my-app, cluster prefix must be my-app or my-app-users).easysam.yaml:
EasySAM automatically inspects Prismarine models during preprocessing to create and register DynamoDB tables, indexes, TTL, and stream triggers in CloudFormation.@c.index(...) decorators ABOVE @c.model(...) decorators.prismarine generate-client Commands in EasySAM:
In EasySAM projects, Prismarine client code (prismarine_client.py) is automatically generated as an integrated step of easysam generate . and easysam deploy .. Do NOT run separate prismarine generate-client CLI commands.access-module for Environment-Suffixed Tables:
When deploying multi-environment stacks, tables are suffixed with stage/environment names. Configure access-module: common.dynamo_access in resources.yaml and create a DynamoAccess module exporting get_dynamo_access(). Consumer code MUST NEVER construct table names manually or call low-level _put_item directly—always use generated model methods (Model.put(), Model.get()).DbConditionFailed for Conditional Writes:
Pass ConditionExpression to put() for atomic conditional writes. Import DbConditionFailed from prismarine.runtime to catch ConditionalCheckFailedException.modelling Mode with Model Parent Class:
Explicitly set modelling: typed-dict or modelling: pydantic in resources.yaml. Models MUST inherit from TypedDict when using typed-dict mode, or BaseModel when using pydantic mode.When integrating Prismarine with EasySAM, use the following package structure:
my-project/
├── resources.yaml # Root config with prismarine: section
├── common/
│ ├── dynamo_access.py # Access module for environment-suffixed tables
│ └── myobject/
│ ├── models.py # Prismarine Cluster & model definitions
│ └── prismarine_client.py # Auto-generated client code (created by easysam generate/deploy)
├── backend/
│ └── function/
│ └── my-function/
│ ├── easysam.yaml # Lambda function definition
│ └── index.py # Handler importing common.myobject.prismarine_clientcommon/myobject/models.py)from typing import TypedDict, NotRequired
from prismarine.runtime import Cluster
c = Cluster('MyApp')
@c.index(index='by-email', PK='Email') # Must be ABOVE @c.model
@c.model(PK='Id', SK='Type', ttl='ExpireAt', trigger='itemlogger')
class UserRecord(TypedDict):
Id: str
Type: str
Email: str
Name: str
ExpireAt: NotRequired[int]resources.yamlprefix: my-app
python: 3.12
prismarine:
default-base: common
access-module: common.dynamo_access
modelling: typed-dict # or: pydantic
tables:
- package: myobject
trigger: true # Preserve model-defined triggersSimply run standard EasySAM commands. EasySAM handles Prismarine table preprocessing and client generation internally:
# Preprocesses models, validates schema, generates template, and writes prismarine_client.py
uv run easysam --environment dev generate .
# Builds and deploys application and Prismarine models to AWS
uv run easysam --environment dev --aws-profile <profile> deploy .(Note: Standalone prismarine generate-client CLI usage is only for non-EasySAM standalone projects).
from common.myobject.prismarine_client import UserRecordModel
from prismarine.runtime import DbNotFound, DbConditionFailed
# Create / Replace
UserRecordModel.put({'Id': 'usr_123', 'Type': 'profile', 'Email': 'user@example.com', 'Name': 'Alice'})
# Conditional Write
try:
UserRecordModel.put(
{'Id': 'usr_123', 'Type': 'profile', 'Email': 'user@example.com', 'Name': 'Alice'},
ConditionExpression='attribute_not_exists(Id)',
)
except DbConditionFailed:
pass # Item already exists
# Get
try:
user = UserRecordModel.get(Id='usr_123', Type='profile')
except DbNotFound:
user = None
# Query Secondary Index
users = UserRecordModel.ByEmail.list(Email='user@example.com')resources.yaml, stream triggers, conditional tables, TTL).@c.model, @c.index, @c.export API & Pydantic mode.get, put, update, save, delete, list, scan).6c052f2
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.