Guides
Outcomes
Let automations write their result back to a record, safely.
Use a record outcome to save an automation's result to the record that triggered it. The write
uses that model's access rules and approval policy.
Naming the Record and the Field
The run payload names the record:
{ "record": { "model": "customer", "id": 42 } }
The outcome's target names the field: { action: 'record', target: 'summary' }. The value
written is the run's output, as text.
Writing to an Agentic Model
Allow the field in the model with outcomes.writable:
export default defineAgenticModel(customers, {
// …
access: { list: 'member', get: 'member', create: 'admin', update: 'admin', delete: false },
agent: { tools: ['list', 'get', 'update'], approval: { update: 'always' } },
outcomes: { writable: ['summary'] },
})
The write follows these model rules:
- Only fields in
outcomes.writablecan be written; anything else fails with403. The list accepts only fields the model can write, so notid,ownerId,workspace, timestamps,hidden, orreadonlyfields, and it requires anupdaterule inaccess. - The automation's actor needs the model's
updaterole, and the record must be in scope. - The model's approval policy applies: with
update: 'always', the change waits in the approvals inbox before it is written.
Writing to Your Own Tables
For another table, provide an updateRecord adapter. The adapter must authorize the row and
allow only the fields you choose:
import { and, eq } from 'drizzle-orm'
import { tickets } from './database/tickets'
export default defineNuxtAgentic({
async updateRecord({ model, id, field, value }, { database, actor }) {
if (model !== 'ticket' || field !== 'resolution') {
throw new Error('Only ticket resolutions can be updated.')
}
await database
.update(tickets)
.set({ resolution: value })
.where(and(eq(tickets.id, Number(id)), eq(tickets.workspace, actor.workspace)))
},
})
In Void, pass the same function as updateRecord to defineVoidAgentic.
The change also carries runId, runAs, and an idempotencyKey unique to the run, so an
adapter can ignore a retried write. The second argument has database, actor, env, and
signal.
Before your adapter runs, some targets are always refused:
- Agentic and auth records:
agent,automation,automationRun,automationFolder,connection,integrationConnection,integrationApproval,approval,organization,member,user,session,account,verification,oauthState, and any model starting withagentic_. - The fields
id,owner,workspace,permissions, androle, and fields ending inIdor_id.
Without an updateRecord adapter, a record outcome for a model that is not registered fails.