All docs
Examples
Hosted workflow

SQLAlchemy Postgres plus Synapsor

Use SQLAlchemy for Python app transactions and Synapsor for governed agent workflows.

Problem

A Python service needs model-facing access to business rows without giving the model a SQLAlchemy session or raw SQL.

Why app glue gets messy

Prompt-only safety does not provide tenant-enforced evidence, proposals, or replay.

How Synapsor helps

Synapsor uses SESSION/HIDDEN bindings and external mappings while SQLAlchemy stays in trusted server code.

Value sources

Example names and seed ids are developer-defined. SESSION values are set by your backend. ARG values come from the SDK/HTTP call. Handles such as wrp://..., evidence://..., and agent-run://... are returned by Synapsor and should be stored for audit/replay.

Read the value-source guide
Expected outcome

Agents answer with evidence and propose writes that Python workers can apply after approval.

Production checks

  • Do not pass SQLAlchemy sessions to model tools.
  • Keep trusted scope in SESSION/HIDDEN fields.
  • Apply approved proposals in SQLAlchemy transactions.
  • Store Synapsor handles where audit needs them.
schema.sql
class Ticket(Base):
    __tablename__ = "tickets"
    id = mapped_column(String, primary_key=True)
    tenant_id = mapped_column(String, nullable=False)
    status = mapped_column(String, nullable=False)
agent.ddl.sql
CREATE AGENT WORKFLOW support.sqlalchemy_ticket_flow
SESSION REQUIRE tenant_id, principal, current_ticket_id
ALLOWED CAPABILITIES (support.answer_ticket_question, support.propose_ticket_resolution)
EVIDENCE REQUIRED
AUTO BRANCH ON PROPOSAL
CHECKPOINT EVERY STEP;
python
ticket = session.get(Ticket, ticket_id)
db.set_session({"tenant_id": user.tenant_id, "principal": user.id, "current_ticket_id": ticket.id})
result = db.capabilities.invoke("support.answer_ticket_question", {"question": question}, response_envelope=True)