All docs
Examples
Hosted workflow

Existing MySQL ecommerce agent

Connect a MySQL ecommerce database for scoped order answers and proposal-based refund status updates.

Problem

An ecommerce assistant needs order and refund policy context but should not receive a raw MySQL credential or write tool.

Why app glue gets messy

Order support workflows touch money, customer status, refund policy, and email/provider side effects.

How Synapsor helps

Synapsor imports selected MySQL tables, binds tenant/order scope from SESSION, records evidence, and stages refund notes/status changes as approved writeback proposals.

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

The agent can answer order questions and propose refund-related updates while MySQL remains the app source of truth.

Production checks

  • MySQL stays the source of truth.
  • Imported tables use allowlisted columns and tenant filters.
  • Refund policy evidence is tied to the capability result.
  • Approved proposal writeback is performed only by the trusted worker.
schema.sql
-- Existing MySQL app tables.
CREATE TABLE customers (
  id VARCHAR(64) PRIMARY KEY,
  tenant_id VARCHAR(64) NOT NULL,
  name VARCHAR(255) NOT NULL,
  email VARCHAR(255)
);

CREATE TABLE orders (
  id VARCHAR(64) PRIMARY KEY,
  tenant_id VARCHAR(64) NOT NULL,
  customer_id VARCHAR(64) NOT NULL,
  status VARCHAR(64) NOT NULL,
  total_cents INT NOT NULL,
  refund_note TEXT,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE refund_policies (
  id VARCHAR(64) PRIMARY KEY,
  tenant_id VARCHAR(64) NOT NULL,
  title VARCHAR(255) NOT NULL,
  body TEXT NOT NULL,
  version INT NOT NULL
);
agent.ddl.sql
CREATE AGENT WORKFLOW ecommerce.order_resolution_flow
SESSION REQUIRE tenant_id, principal, current_order_id
ALLOWED CAPABILITIES (
  ecommerce.answer_order_question,
  ecommerce.propose_order_refund_note
)
EVIDENCE REQUIRED
AUTO BRANCH ON PROPOSAL
CHECKPOINT EVERY STEP
ON RISK medium REQUIRE APPROVAL ROLE 'commerce_lead';

CREATE AGENT CONTEXT ecommerce.order_context
ROOT EXTERNAL external_shop.orders AS order
LOOKUP order.id = SESSION current_order_id
BIND tenant_id FROM SESSION tenant_id
BIND principal FROM SESSION principal
JOIN EXTERNAL external_shop.customers AS customer
  ON customer.id = order.customer_id
  AND customer.tenant_id = SESSION tenant_id
SEARCH EXTERNAL external_shop.refund_policies AS policy_hits
  USING TEXT(refund_policies.body)
  QUERY ARG question
  FILTER refund_policies.tenant_id = SESSION tenant_id
  TOP 5
OUTPUT SLOTS
  order_id AS order.id,
  order_status AS order.status,
  total_cents AS order.total_cents,
  customer_name AS customer.name,
  policy_hits AS policy_hits
EVIDENCE ON;

CREATE AGENT CAPABILITY ecommerce.answer_order_question
ARG question TEXT REQUIRED
HIDDEN tenant_id FROM SESSION tenant_id
HIDDEN principal FROM SESSION principal
HIDDEN current_order_id FROM SESSION current_order_id
USE CONTEXT ecommerce.order_context
EXECUTION READ ONLY
REQUIRES EVIDENCE
RETURN ANSWER WITH CITATIONS;

CREATE AGENT CAPABILITY ecommerce.propose_order_refund_note
ARG order_id TEXT REQUIRED
ARG refund_note TEXT REQUIRED
HIDDEN tenant_id FROM SESSION tenant_id
HIDDEN principal FROM SESSION principal
USE CONTEXT ecommerce.order_context
EXECUTION PROPOSAL
REQUIRES EVIDENCE
WRITE PROPOSAL TARGET EXTERNAL external_shop.orders
OPERATION UPDATE
LOOKUP id FROM ARG order_id
TENANT tenant_id FROM BINDING tenant_id
COLUMNS refund_note FROM ARG refund_note
AUDIT ecommerce.order_audit;
python
db.set_session({
    "tenant_id": "acme",
    "principal": "commerce_agent_4",
    "current_order_id": "O001",
})

run = db.agent_runs.start(
    workflow="ecommerce.order_resolution_flow",
    input={"order_id": "O001"},
)

answer = run.invoke_capability(
    "ecommerce.answer_order_question",
    step_key="answer_order",
    arguments={"question": "Is this order eligible for a refund?"},
    response_envelope=True,
)