Watch the machine change state.
This is the proposed Samora agent runtime, shown one function, transaction, row, signal, and decision at a time. It uses a campaign recovery goal because the same mechanism must operate across Samora, not only on leads.
"Find why the September renewal campaign stalled. Retry only safe failures. Ask me before relaunching anything, then monitor the result."
Trace choice. This example activates a fully validated goal in the create transaction. The current technical specification describes creation as a draft. Samora must choose one contract. If draft remains the contract, insert a separate authenticated start transaction before the first outbox wake. A stored Temporal workflow ID reserves identity; it does not prove the workflow has started. Readable IDs such as goal_01, exec_77, and step_78 are trace aliases for UUID values.
The user submits an objective
The chat holds the request long enough to send an authenticated goal command. Nothing durable exists yet.
Rows at this step
0 operationsCausal and changed fields are shown. Routine timestamps and soft-delete fields are omitted unless they affect the transition.
Committed row ledger
0 rowsFunction and transaction inspector
current frame- Function
- Starts because
- Reads
- Transaction
- Commit causes
- If it fails
- Temporary state
agentic.events and the existing workflows.step_events audit row. It does not create a generic Activity record.The facts that caused this frame
What happens when the clean path breaks
The system does not infer success from silence. Each branch leaves a durable reason for stopping, retrying, reconciling, or asking a person.
The only useful database trigger is a doorbell
Business orchestration does not belong in a PostgreSQL trigger. The transaction writes an outbox fact. An optional trigger can wake a relay sooner, but the relay still polls because notifications can disappear.
INSERT agentic.outboxThe row is still inside the business transaction.agentic.notify_outbox_ready()The AFTER INSERT trigger queues pg_notify(outbox_id) inside the same transaction.COMMITThe row becomes durable and PostgreSQL releases the best-effort notification. Rollback releases neither.Tables the machine needs
[P] means proposed. [E] means Samora has the table or path now. Domain tables stay authoritative for campaigns and workflow executions.
agentic.goalsThe durable objective, status, owner, limits, request key, current revision, and reserved Temporal identity.
agentic.goal_revisionsImmutable user wording, scope, authority, success, and stop rules.
agentic.subject_runsOne independently progressing campaign, agent, conversation, lead, tool, or other typed subject.
agentic.eventsAppend-only facts that explain every wake and state change.
agentic.context_snapshotsThe immutable evidence manifest used by one decision turn.
agentic.decision_turnsModel, prompt, input hash, proposal, evidence, usage, and outcome.
agentic.work_itemsAuthorized work with target, version, conflict key, repeat-protection key, lease owner, lease token, and lease expiry.
agentic.work_dependenciesApproval and predecessor rules that keep blocked work from running.
agentic.wait_conditionsEvent match, deadline, state, and the event that satisfied the wait.
agentic.action_attemptsA record written before each external effect, with the stable logical action key.
agentic.approvalsThe exact action, allowed decider, expiry, target version, and immutable decision.
agentic.outboxA delivery promise with next attempt, claim token, claim deadline, receipt, and guarded acknowledgement.
campaigns.campaignsCurrent campaign configuration and version. Agentic state references it, never copies it.
campaigns.recipientsThe campaign's per-contact projection and workflow execution link.
workflows.executionsThe read model for a ContactWorkflow. Temporal still owns progression.
workflows.execution_stepsOne channel attempt. It binds node, attempt, call or message, conversation, lifecycle, and result.
workflows.step_eventsThe existing node audit line. A manual retry writes here after the new Temporal run starts.
conversations.conversationsThe conversation created for the retried channel action.
conversations.conversation_assignmentsThe AI agent assignment created with the conversation when required.
voice.callsThe authoritative voice call lifecycle. A status trigger publishes a best-effort notification after commit.
dispatch.jobsThe provider job with producer key, claim lease, unknown state, and voice reconciliation.
Open data-model gaps
The technical specification names behaviors that its first table list does not fully store. These need explicit design before migrations.
The messages API says it writes a message, but no goal_messages table is defined.
The audit section requires a rule-versioned policy result, but no separate policy-decision row exists.
Completion needs evidence and exceptions. A first-class resolution record is absent.
Outbox delivery exists, but per-consumer delivery and acknowledgement are not specified.
The runtime promises reservations and conflict keys without a durable reservation or claim ledger.
Campaigns have a numeric version. Several existing Samora resources do not yet have one for safe compare-and-set writes.
The existing retry endpoint accepts node_id and requested_by. It does not accept the agentic action key or campaign version. The adapter and store guard are required changes.
The current voice status router writes timeline rows and signals Temporal without an outbox transaction. Domain rows permit reconciliation, but generic repair is incomplete.
What changed this cycle
The animation now follows the full request through 52 frames. The changes are documentation only.
tmp/agent-runtime-frames.json now carries 52 ordered frames, guarded replay keys, live claim checks, work leases, corrected timestamps, and the existing voice result path.
This file embeds the same 52-frame payload. It shows staged rows, commits, reads, triggers, external calls, waits, reconciliations, and final receipts.
session-2026-09-04-samora-openai-agents-sdk-technical-spec.html now names the workspace-scoped request and event keys plus the fields needed for safe claims and acknowledgements.
reports/index.html identifies this as a 52-step trace and keeps its search and category metadata.
The trace now mirrors the real conversation, assignment, call, dispatch job, execution step, step event, router, and reconciliation paths.
No application table changed. No generic Activity row was created. Every row on this page is an illustrative snapshot.
Decision made for this design
The database records truth. Temporal owns long waits. Short-lived workers reason or execute one bounded unit, then disappear.
Do not make an agent process the owner of a goal
Why: a goal can wait for hours or weeks. Keeping a model or worker alive wastes resources and loses continuity on deploy or crash.
Alternative rejected: one permanent agent per campaign or lead. Worker identity would become hidden state and would make failover unsafe.
Trade-off: Samora must build durable context assembly, decisions, work, waits, approvals, attempt records, outbox delivery, and reconciliation around the OpenAI Agents SDK.
Verified Samora paths behind the trace
These are plain source citations in this public copy. Service source is not uploaded.
pgxdb.WithinTransaction, transaction wrappersamora-be/database/pgxdb/pgxdb.go:34-86- transaction-aware job enqueue
samora-be/jobs/enqueuer.go:20-147 - Temporal owns progression; PostgreSQL is a read model
samora-be/database/schemas/workflows.sql:1-18 - workspace membership and role columns
samora-be/database/schemas/auth.sql:87-108 - workspace access and permission derivation
samora-be/services/auth_service/service.go:899-935 - execution-step and step-event rows
samora-be/database/schemas/workflows.sql:177-255 - dispatch job, lease, and result fields
samora-be/database/schemas/dispatch.sql:85-130 - the existing post-commit voice status notification
samora-be/database/schemas/notifications.sql:103-132 - conversation and AI assignment inserts
samora-be/services/workflow_dispatch_service/dao.go:714-756 - voice call creation
samora-be/services/workflow_dispatch_service/dao.go:1196-1205 - existing retry, Temporal start, run binding, and retry event
samora-workflows/internal/httpapi/executions.go:74-170 - execution-step creation and logical attempt key
samora-workflows/internal/store/store.go:330-359 - voice status routing and outcome signal
samora-workflows/internal/triggers/router.go:138-223 - dispatch job claim
samora-dispatcher/internal/store/jobs.go:226-274 - voice worker workspace selection and claim call chain
samora-dispatcher/internal/voice/worker.go:140-224 - unknown voice dispatch reconciliation
samora-dispatcher/internal/reconcile/reconciler.go:287-349 - step result and result event
samora-workflows/internal/store/store.go:420-443 - execution and recipient completion transaction
samora-workflows/internal/store/store.go:213-250 - proposed persistent data model in the technical specification
Acceptance quiz
PENDING · 0 / 8 ANSWEREDThe user has not answered these yet. A score of 7/8 is required before this major documentation change can be accepted.
1. What becomes durable before Temporal starts the goal workflow?
Correct answer: the goal, immutable revision, request event, and pending outbox row commit first.
2. Why is pg_notify not the source of truth?
Correct answer: notifications may be missed or repeated. The committed outbox row is durable, and a poller repairs delivery.
3. Is an OpenAI Agents SDK worker alive while the system waits for approval?
Correct answer: no. The approval, wait, and context survive in PostgreSQL and Temporal.
4. What must exist before an external side effect starts?
Correct answer: an authorized work item and a running action-attempt row with the stable logical action key.
5. What happens if the campaign version changes after approval?
Correct answer: the final gate invalidates the stale approval and returns the run for reassessment. It does not execute the old proposal.
6. Which system owns lifecycle progression, and which system owns business facts?
Correct answer: Temporal owns progression, timers, and signals. PostgreSQL owns goals, decisions, approvals, work, events, attempts, and domain rows.
7. If an external outcome is unknown, may Samora create a fresh retry?
Correct answer: no. It must reconcile the same logical action first and reuse its idempotency key if a policy-approved retry becomes safe.
8. Did this documentation session change a product database row or create an Activity row?
Correct answer: no. It created documentation and a visualization only. The displayed database rows are proposed examples.