Secure application integration
The SDK enforces finite record semantics. Your host establishes who is acting, which policy applies, what credentials an adapter receives and whether an external report is authentic. Keep that boundary explicit when agents generate applications.
Authenticate before constructing authority
Section titled “Authenticate before constructing authority”Deny agent attempts to issue new grants · Executable application recipe
import assert from 'node:assert/strict';import {readFileSync} from 'node:fs';import {parseContract,type Command} from '@aiws/sdk';import {SqliteStore} from '@aiws/sdk/sqlite';import {Coordinator,type Authorizer} from '@aiws/sdk/runtime';// Demo session comes from the application, never command.context or an event payload.const session={actor:'agent:builder',isHuman:false};const humanOnly=new Set(['grant','revokeGrant','approve','withdrawApproval']);const allowedCommands=new Set(['startRun']); // deliberately narrow teaching policyconst authorize:Authorizer=async(command)=>{ const allowed=allowedCommands.has(command.type)&&(!humanOnly.has(command.type)||session.isHuman); return {allowed,policy:allowed?'ALLOW':'DENY',mandatoryChecksOk:true, context:{actor:session.actor,policyRevision:'policy:example:1',decisionClass:'DETERMINISTIC'}};};const contract=parseContract(readFileSync('examples/guide/contract.json','utf8'));const store=new SqliteStore(':memory:',contract);const coordinator=new Coordinator(store,authorize,()=> '10');try { await coordinator.apply({type:'startRun',runId:'r'}); const grant:Command={type:'grant',grant:{id:'g',subject:session.actor,profile:'finite-v1',actions:['write'],resources:['doc'],notBefore:'0',expiresAt:'10000',limit:'100',canDelegate:false,depth:'0'}}; await assert.rejects(coordinator.apply(grant),(e:any)=>e.code==='AUTHORITY_DENIED'); assert.equal(store.snapshot().revision,'1'); assert.equal(store.diagnostics()[0].command.code,'AUTHORITY_DENIED');} finally {store.close();}use aiws_sdk::*;use aiws_sdk::runtime::*;use aiws_sdk::sqlite::SqliteStore;use serde_json::json;struct SessionPolicy;impl Authorizer for SessionPolicy { fn authorize(&mut self,command:&Command,_:&Snapshot,_:&str)->Result<Authorization>{ // Deliberately narrow demo agent policy. Identity comes from trusted host state. let allowed=command.as_value()["type"]=="startRun"; Ok(Authorization{allowed,policy:if allowed{"ALLOW"}else{"DENY"}.into(),mandatory_checks_ok:true, context:json!({"actor":"agent:builder","policyRevision":"policy:example:1","decisionClass":"DETERMINISTIC"})}) }}struct FixedClock;impl Clock for FixedClock{fn now_ms(&self)->String{"10".into()}}fn main()->std::result::Result<(),Box<dyn std::error::Error>>{ let contract=Contract::parse(&std::fs::read_to_string("examples/guide/contract.json")?)?; let store=SqliteStore::open(":memory:",Some(&contract))?; let mut coordinator=Coordinator::new(store,SessionPolicy,FixedClock); coordinator.apply(&Command::from_value(json!({"type":"startRun","runId":"r"}))?,None)?; let grant=Command::from_value(json!({"type":"grant","grant":{"id":"g","subject":"agent:builder","profile":"finite-v1","actions":["write"],"resources":["doc"],"notBefore":"0","expiresAt":"10000","limit":"100","canDelegate":false,"depth":"0"}}))?; assert_eq!(coordinator.apply(&grant,None).unwrap_err().code,"AUTHORITY_DENIED"); assert_eq!(coordinator.store.snapshot()?.as_value()["revision"],"1"); assert_eq!(coordinator.store.diagnostics()?[0]["command"]["code"],"AUTHORITY_DENIED"); Ok(())}from pathlib import Pathfrom aiws import parse_contract,AiwsErrorfrom aiws.sqlite import SqliteStorefrom aiws.runtime import Coordinator# Identity is trusted application state, not a caller-supplied command field.session={'actor':'agent:builder','isHuman':False}def authorize(command,state,now): allowed=command['type']=='startRun' # narrow demo policy; everything else is denied return dict(allowed=allowed,policy='ALLOW' if allowed else 'DENY',mandatoryChecksOk=True, context=dict(actor=session['actor'],policyRevision='policy:example:1',decisionClass='DETERMINISTIC'))contract=parse_contract(Path('examples/guide/contract.json').read_text())with SqliteStore(':memory:',contract) as store: coordinator=Coordinator(store,authorize,lambda:'10') coordinator.apply(dict(type='startRun',runId='r')) grant=dict(type='grant',grant=dict(id='g',subject=session['actor'],profile='finite-v1',actions=['write'],resources=['doc'],notBefore='0',expiresAt='10000',limit='100',canDelegate=False,depth='0')) try: coordinator.apply(grant) raise AssertionError('expected denial') except AiwsError as error: assert error.code=='AUTHORITY_DENIED' assert store.snapshot()['revision']=='1' assert store.diagnostics()[0]['command']['code']=='AUTHORITY_DENIED'The example uses a fixed trusted-host identity to demonstrate a denial. Replace it with a verified session, service identity or worker capability from your actual identity system. Do not read isHuman, actor, role or ALLOW from an untrusted request body. An approval record represents a decision only after the host has verified who made it and what they approved.
Permission and resource-limit changes for agents always require human approval under the agreed engine design. Enforce this in the authorizer for every relevant operation. A delegated agent must not edit the policy document or identity claims that would allow it to approve its own expansion.
Limit adapter capabilities
Section titled “Limit adapter capabilities”Give each adapter only the filesystem roots, outbound hosts, credentials and tool actions it needs. Validate artifact references and resolved paths before access. For coding tasks, use an isolated checkout or execution environment with explicit command and network policy. A graph node named VERIFICATION does not sandbox the command used to run a test suite.
Treat source files, retrieved documents, webhook payloads, model output and handoff summaries as untrusted input. Embedded instructions cannot change engine policy, grant capabilities or approve new spending. Keep approved intent and machine-readable controls distinct from narrative context.
Approval and evidence integrity
Section titled “Approval and evidence integrity”Bind approval to the exact canonical action fingerprint and valid use count. Reevaluate current policy at dispatch; admission is not a permanent right to act. Avoid logging approval secrets, callback correlation tokens or provider credentials. Verify callback signatures and replay protections in the host before constructing TriggerEvent.
A digest detects changed content under a trusted reference. It does not establish authorship if an attacker can rewrite both the content and digest. Protect the SQLite database, backups, artifact store and audit exports with access controls. Where attestation is required, add a reviewed application signature/provenance mechanism; the SDK does not supply a universal signature protocol.
Operate with bounded resources
Section titled “Operate with bounded resources”Enforce limits at ingress before parsing, and limit external response sizes and adapter execution time. Choose conservative reservations before dispatch. Monitor the journal and telemetry outbox: disk-backed storage is not an unlimited queue. Do not release an UNKNOWN reservation just to let a new request proceed.
Use secret references in configuration and resolve credentials at execution. Rotate credentials independently of durable workflow history. If a credential expires while a workflow is paused, reauthenticate and reauthorize at continuation rather than relying on a saved token.
Incident handling
Section titled “Incident handling”For suspected tampering or an uncertain side effect, block affected work, preserve IDs and receipts, and route a specific decision to an authorized human. Do not delete history, fabricate verification or automatically broaden permissions as a repair strategy. See recovery and handoffs for the durable record needed to resume safely.