Sorcha.Agent
2.18.1
See the version list below for details.
dotnet tool install --global Sorcha.Agent --version 2.18.1
dotnet new tool-manifest
dotnet tool install --local Sorcha.Agent --version 2.18.1
#tool dotnet:?package=Sorcha.Agent&version=2.18.1
nuke :add-package Sorcha.Agent --version 2.18.1
Sorcha Agent - Autonomous Actor for Decentralised Workflows
Version: 1.0.0 Status: Production Ready
The Sorcha Agent is a cross-platform CLI tool that runs as an autonomous actor in Sorcha decentralised register workflows. It listens for pending actions, makes decisions using pluggable engines (rules or AI), and submits responses — enabling fully automated multi-participant workflow execution.
Installation
# Install as a global tool
dotnet tool install --global Sorcha.Agent
# Verify installation
sorcha-agent --version
Quick Start
1. Create an Actor Definition
Actor definitions are JSON files that configure identity, inbox discovery, and decision-making:
{
"actor": {
"name": "approver",
"description": "Automated approval agent"
},
"connection": {
"gatewayUrl": "http://localhost",
"registerId": "your-register-id",
"credentials": {
"email": "$env:AGENT_EMAIL",
"password": "$env:AGENT_PASSWORD",
"organizationId": "your-org-id"
},
"walletAddress": "your-wallet-address"
},
"inbox": {
"signalR": { "enabled": true },
"polling": { "enabled": true, "intervalSeconds": 30 }
},
"mode": "rules",
"rules": [
{
"actionName": "Review Request",
"condition": { "==": [true, true] },
"decision": "approve",
"payload": {
"approved": true,
"notes": "Auto-approved by agent"
}
}
]
}
2. Validate Configuration
sorcha-agent validate --config actor.json
This checks JSON structure, variable resolution, authentication, and SignalR connectivity.
3. Run the Agent
sorcha-agent run --config actor.json
The agent will authenticate, connect to the inbox, and begin processing actions autonomously.
Commands
| Command | Description |
|---|---|
sorcha-agent run --config <path> |
Start the autonomous actor loop |
sorcha-agent validate --config <path> |
Pre-flight configuration checks |
sorcha-agent haip receive --offer-uri <uri> |
Receive a credential via OID4VCI pre-authorized code flow |
sorcha-agent haip present --request-uri <uri> |
Present a credential via OID4VP direct_post |
Options
| Option | Description |
|---|---|
--config |
Path to actor definition JSON (required) |
--state |
Path to state.json for placeholder resolution |
--verbose |
Enable debug-level logging |
--quiet |
Errors only |
HAIP Wallet Commands
The agent can act as a simulated HAIP wallet for end-to-end testing of OpenID4VCI and OpenID4VP flows. These commands are standalone (they do not use actor JSON files or the autonomous loop) and operate on a local file-based wallet directory.
Receive a Credential (OpenID4VCI)
sorcha-agent haip receive --offer-uri <uri> --wallet-dir ./wallet
Executes the OID4VCI pre-authorized code flow:
- Parses the
openid-credential-offer://URI to extract the offer JSON - Fetches issuer metadata from
/.well-known/openid-credential-issuer - Exchanges the pre-authorized code for an access token and
c_nonce - Builds a JWT proof of possession binding the holder key to the nonce
- Requests the credential at the credential endpoint
- Stores the SD-JWT VC in
<wallet-dir>/credentials/<CredentialType>.sdjwt
| Option | Required | Default | Description |
|---|---|---|---|
--offer-uri |
Yes | - | OpenID4VCI Credential Offer URI |
--wallet-dir |
No | ./wallet |
Directory for keys and credentials |
--key-file |
No | <wallet-dir>/holder-key.pem |
Path to holder key PEM file |
Present a Credential (OpenID4VP)
sorcha-agent haip present --request-uri <uri> --credential VerifiedIdentityCredential --disclose "givenName,familyName,dateOfBirth" --wallet-dir ./wallet
Executes the OID4VP direct_post flow:
- Loads the specified credential from the wallet
- Fetches the authorization request object from the request URI
- Builds a selective disclosure presentation with only the specified claims
- Signs a KB-JWT (Key Binding JWT) with the holder key, binding nonce and audience
- Submits the
vp_tokenviadirect_postto the verifier's response URI
| Option | Required | Default | Description |
|---|---|---|---|
--request-uri |
Yes | - | OpenID4VP Authorization Request URI |
--credential |
Yes | - | Credential type to present (e.g., VerifiedIdentityCredential) |
--disclose |
Yes | - | Comma-separated claim names to disclose |
--wallet-dir |
No | ./wallet |
Directory for keys and credentials |
Exit Codes (HAIP commands)
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error (invalid URI, missing credential, unexpected failure) |
| 2 | Authentication error (token exchange failed, request object fetch failed) |
| 3 | Credential/presentation rejected by server |
| 4 | Network or metadata error |
Wallet Directory Structure
The HAIP commands use a flat file-based wallet:
wallet/
├── holder-key.pem # ES256 (P-256) private key — auto-generated on first use
├── holder-key.jwk.json # Public JWK for reference
└── credentials/
├── VerifiedIdentityCredential.sdjwt
└── DrivingLicenceCredential.sdjwt
Holder Key
The holder key is an ECDSA P-256 (ES256) key pair used for:
- JWT proof of possession during credential issuance (binds the credential to this key via
cnf) - KB-JWT signing during credential presentation (proves the presenter holds the key)
The key is generated on first use and persisted as a PEM file. Subsequent receive and present invocations reuse the same key. Both walkthroughs in walkthroughs/HaipIdentityAttestation/ and walkthroughs/HaipDrivingLicence/ share the same wallet directory and holder key.
Important Notes
- IssuerUrl resolution: The issuer URL embedded in the credential offer must be host-resolvable (typically
http://127.0.0.1when running against Docker). The agent runs on the host machine and must reach the issuer's metadata, token, and credential endpoints directly. - Issuer JWK in header: In dev/walkthrough mode, the issuer's public JWK is embedded in the JWS header. Production deployments use
x5ccertificate chains. - No authentication required for HAIP commands: Unlike the
runandvalidatecommands, the HAIP commands do not authenticate against Sorcha. They interact directly with the OID4VCI/OID4VP endpoints using the pre-authorized code or presentation request URI.
Decision Engines
Rules Engine (JSON Logic)
Deterministic rule evaluation using JSON Logic syntax. Rules are evaluated top-to-bottom; first match wins.
{
"mode": "rules",
"rules": [
{
"actionName": "Cost Approval",
"condition": { ">": [{ "var": "payload.cost" }, 500000] },
"decision": "reject",
"payload": { "reason": "Exceeds budget threshold" }
},
{
"actionName": "Cost Approval",
"condition": { "==": [true, true] },
"decision": "approve",
"payload": { "approved": true }
}
]
}
AI Engine (Claude)
LLM-powered decisions using a persona prompt and action context:
{
"mode": "ai",
"ai": {
"provider": "anthropic",
"model": "claude-sonnet-4-6",
"temperature": 0.3,
"personaFile": "./persona.md",
"apiKeyEnvVar": "ANTHROPIC_API_KEY"
}
}
Variable Resolution
$env:VAR_NAME— Resolved from environment variables (recommended for secrets){{placeholder}}— Resolved from astate.jsonfile (useful for dynamic IDs from setup scripts)
Pre-Actions
Hooks that execute before payload submission, e.g. file uploads:
{
"preActions": [
{
"type": "file-upload",
"config": {
"fieldName": "document",
"filePath": "./report.pdf",
"fileName": "report.pdf",
"contentType": "application/pdf"
}
}
]
}
Features
- Dual Inbox Discovery — Real-time SignalR + configurable HTTP polling with automatic deduplication
- Pluggable Decision Engines — Rules (JSON Logic) or AI (Claude) with schema validation
- File Upload Pre-Actions — Chunked encrypted file submission (up to 40MB)
- Resilient Execution — Polly retry/circuit-breaker, SignalR auto-reconnect, JWT auto-refresh
- Audit Logging — JSONL append-only trail of all decisions and submissions
- Persona Mode — Optional autonomous initiator loop alongside reactive inbox (Feature 110)
- Cross-Platform — Runs on Windows, macOS, and Linux
Persona Mode
A persona is an optional JSON file that lets an agent initiate a workflow instead of only reacting to its inbox. Enabled by adding a personaFile field to the actor definition:
{
"actor": { "name": "procurement-mgr", ... },
"personaFile": "../personas/procurement-mgr-kickoff.persona.json",
"mode": "rules",
"rules": [ ... ]
}
The persona file declares a trigger (once in v1), a target (blueprint + instance + action index), and a payload template with substitution tokens (${now}, ${uuid}, ${counter}, ${random.int|decimal|choice}). The persona loop runs alongside the reactive inbox loop using the same wallet, auth, and HTTP client — agents without personaFile are unaffected.
Typical use is unblocking multi-agent walkthroughs that would otherwise hang because the first action has no prior transaction to populate any agent's inbox. See specs/110-agent-persona-mode/quickstart.md for the full guide.
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Authentication error |
| 4 | Validation error |
| 6 | Configuration error |
| 7 | Network error |
| 8 | Service error |
Requirements
- .NET 10 runtime
- Access to a running Sorcha platform instance
- Valid user credentials with wallet access
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.