Driving credenco-cli from an AI Agent
An AI agent with a shell can operate a Business Wallet through credenco-cli. Below are five
plain-English requests, the commands an agent turned them into, and the real output.
Examples
"Which credentials are stored in Ada's wallet?"
Ada is the holder who receives the Bank Account credential in the issue example below. Her wallet
has its own profile, ada.
Which credentials are stored in Ada's wallet?
Bash(credenco-cli --profile ada credential list-wallet-holder-credentials | jq '.content[] | {type, credentialStatus, issuedAt, claims: (.payload | {iban, account_name, currency, account_type})}')
{
"type": "BankAccountCredential",
"credentialStatus": "VALID",
… +8 lines (ctrl+o to expand)
One valid BankAccountCredential, issued on 2026-10-13 at 14:26:
| Claim | Value |
|---|---|
iban | NL91ABNA0417164300 |
account_name | Ada Lovelace |
currency | EUR |
account_type | checking |
"I want to issue Bank Account credentials with the attributes iban, account_name, currency and account_type. Make the configuration for me"
This is two objects, not one: an issuer template (the OpenID4VCI credential issuer) and a credential template inside it (the credential's format, type and claims).
I want to issue Bank Account credentials with the attributes iban, account_name, currency and account_type. Make the configuration for me
Bash(credenco-cli issuer-template create-issuer-template --issuer-template-key bank-account-issuer …)
{
… +13 lines (ctrl+o to expand)
Issuer template bank-account-issuer is created, with interop profile DIIP_V5. The credential template needs the identifier that signs the credential, so I look that up first.
Bash(credenco-cli identifier list-identifiers | jq -r '.content[] | select(.defaultIdentifier) | .externalKey')
f8124ef0-bf81-46fe-9655-5a2b3864ade9
Bash(credenco-cli credential-template create-credential-template bank-account-issuer --body @- <<'JSON' …)
{
"attributes": [
{
… +34 lines (ctrl+o to expand)
Created credential template bank-account-sd-jwt under bank-account-issuer, format SD_JWT:
| Attribute | Mandatory | Selectively disclosable |
|---|---|---|
iban | yes | yes |
account_name | yes | yes |
currency | no | yes |
account_type | no | yes |
The response echoes the stored template, so the agent can confirm the four claims landed in order rather than assuming they did.
--dry-run on either command prints the request it would send, with the key redacted. It is the
cheapest way to review an agent's interpretation of a request like this one before anything is
created.
"Test the issue of the Bank Account credential"
issue is one of the four workflow commands. It creates the offer, prints the offer URI and a
QR code to standard error, and polls the status until it is terminal. The agent only has to read
the final status from standard output.
Test the issue of the Bank Account credential
Bash(credenco-cli issue bank-account-sd-jwt \
--claims '{"iban":"NL91ABNA0417164300","account_name":"Ada Lovelace","currency":"EUR","account_type":"checking"}')
Scan or open:
openid-credential-offer://?credential_offer_uri=https%3A%2F%2Fwallet.acc.credenco.com%2Fpublic%2F2a0ae7d8-2b17-4d05-94ab-02a1cc74606f%2Fbank-account-issuer%2FcredentialOffer%3Fid%3Dbfbc0336-7f8c-49d6-9d4f-4d83f4abb1e4
█████████████████████████████████████████████████████████████
█████████████████████████████████████████████████████████████
████ ▄▄▄▄▄ ██▄▀█ ▄▄█▄██▄▄█▀▀ ██▄ ██▄ ▀ ▄ ▀██ ▄▄▄▄▄ ████
████ █ █ █▄▄▀▀ ██ ▀█▀▄▄█ ▀ █▀ ▄██ ▄▄██ ▄██▀▄▀█ █ █ ████
████ █▄▄▄█ ██▄▀█▄█▀█▄ █ █▀ ▄▄▄ ▀ █▀▄ █ ███ █▄▄▄█ ████
████▄▄▄▄▄▄▄█ █ ▀ ▀ ▀▄▀ ▀▄█▄█ █▄█ █▄▀▄█▄▀ █ ▀ ▀ █ █▄▄▄▄▄▄▄████
████▄▄▄█ ▄▄▄▄█▀ ██ ███ ▄ ▄▄ ▄█ █▄▄▄█▄▄▄▀█ █▄▄▀█▀▄▀▀████
████▄ █ ▄█▄▀▀█▄▄█▄██▀▀ █▄▄█ █▄██ ██▀ ▀ ▀▄▄█▀▀▀▀███▄ ▀█ ████
████▄ █ ▀▄▄██ ▀▀█ █ █▀ █▄▄▀▀ ▄ ▄▄▄▄▄▄▄▄ ███▀█▀▄▀▀ ▀████
████ ▀▄▄▄▄▄▀▄▀▀█▄█▄▀█▀ ▄▄████ ▄█ █▄ ██▄ █▀▀▀█▀ ▄ ▀▄ ▄▄▄▄████
████▄▄▄█▀ ▄ ▄▄▀▄█▄ ▄█ █ █▀ ██ ▄▄█▄█▄█▄▄█ ▄ █▄█▄▄ █▀▀ ████
████▄▀▄ █▄▄▀▀▄█▀ ▄ ▄█▄██▄▄█████ ▀█ ▄ █▀▀██ █▀▄▄▀█▄▀ ▄▄▄████
██████▀▀▀▀▄█▄█▄█▄ ███ ▀██ ██▀ ▄█▄ ▄▄ ▄▄▄▄▄▄▄██▀▄█ ▄█ ████
████▀▀█ ▀▀▄▄█▀ ▀ ▀▀██▄ █ ▄▀█▄█▄ █ ▀ ▀█ ▄▀▄▀█▀▀█ █ ▀▄ ▄████
████▄ ▄ ▄▄▄ ▀██▄ ██ ███ ▄ ▄▄▄ █▄▀ █▄ ▄█ ██ ▄▄▄ ▀█ ████
█████▄ █▄█ ▄▄▀▄ ▄█▀▀▄ █▀ ▄ █▄█ ██▄ ▄▀▀ ▀█ ▀ █ █▄█ ▀▄ ▄████
█████▀ ▄▄ ▄ ▄▀ ▄█ █ ██ ▄▄▄ ▄█▄█▄█▄▄▄▀█▀▄▄▄█ ▄▄▄▄▄▀█ ████
████▄ ▄▀▀█▄█ ██ ██▄▄ ▄▄ ▄▀ ▄▄ ██▀ ▄▀▄▄ ██ █▀█ ▄▄▄▄█▄████
█████▀▄▄▄█▄█▄ ▄ ██▄ ▄█ █ █ ▀▄█▄ █▄▄██▄▄▄██ █▀██▀████
████ ▀ ▀▀▄▀██▀██▀▄ ▄█▄▀ ██ ██▀█▀ █▀ ██▄ ▀██ ███▄ ████
████▀██▄ ▀▄▄█▄██▄█ ▀█ ██▄ ███ ▄██▀ ▄█ ▄ ▄██ ███▀█▄▀████
████▄ ▄ █ ▄ ▄ █▄▄ ▀▀ ▄█ ▀▀ ▄ ████ ███ ▄█ ▀▀█▀ ▀ █▄▄██▄████
██████▄▀█▄▄ ▀▀ ██ ▀▄ █▀ ▄ █▄▄█▄ ▄▄ ██ ▄▄██▄ ██ █ ▀████
████▄ ▀▄▄▄▄ ▄ ▄ ███▀▄▄█▄▀▄█ ▀███▄█▄ ▄█▄▀▀█ ██ ▀ █ ▄▄▄████
███████▄██▄▄▀▄▄▄██▄ ██ ██▄ ▄▄▄ ██▄▄██▄ ██▄▄▄██ ▄▄▄ █▀▀████
████ ▄▄▄▄▄ █ ▀▀▀▄▄██▄ ▀▀█▄█ █▄█ ██ ▀██▄█▄ ▀█▄ █▄█ ███▄████
████ █ █ █▄▀▀█▄▀ ▄ ████ █ ▄▄ ▀▄█▄▄█ ▄▄▄▄██▄ ▄ ▀█▄▄████
████ █▄▄▄█ █ ▄ █▀▀▄ ▄▄ █▄▄▄▀ ██ ▀▀█▀ █▄▀ ▄█▄ █▀█▄▄▄▄▄▄▄ █████
████▄▄▄▄▄▄▄█▄██▄█████▄▄██▄▄▄▄▄▄▄▄██▄▄██▄▄██▄▄▄█▄▄██▄▄██▄▄████
█████████████████████████████████████████████████████████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
status: issue_request_created
status: credential_offer_retrieved
status: issue_completed
{
"correlation_id": "0a590152-d44a-4b5b-8745-b7eb93bf82bf",
… +5 lines (ctrl+o to expand)
The wallet accepted the offer: the issuance ended with status issue_completed (correlation id 0a590152-d44a-4b5b-8745-b7eb93bf82bf).
Two things an agent has to get right here:
- A credential offer needs a holder. The flow only reaches
issue_completedonce a wallet accepts the offer. An agent working unattended should pass--wait=false, hand therequest_urito whoever is holding the phone, and pollcredenco-cli issue-credential get-credential-issuance-status <correlation_id>afterwards. awaiting_confirmationis terminal for this command, but not for the flow. It means the issuance is waiting for an out-of-band confirmation at a desk. Polling longer will not move it;credenco-cli issue-credential confirm-credential-issuance <correlation_id> --confirmation-code <code>will.
"I want to receive BankAccount credentials, with the iban and account_name attributes. Make the configuration for me"
Receiving a credential is a verifier template: a purpose shown to the holder plus a DCQL query naming the credential type and the exact claims wanted. This is the request where an agent earns its keep, because the mapping from the sentence to DCQL is mechanical but easy for a person to get wrong.
I want to receive BankAccount credentials, with the iban and account_name attributes. Make the configuration for me
Bash(credenco-cli verifier-template create-verifier-template --body @bank-account-check.json --dry-run)
{
"dryRun": true,
"method": "POST",
… +39 lines (ctrl+o to expand)
This is the request I would send. It is a dry run, so nothing is created yet:
- Verifier template
bank-account-check, interop profileDIIP_V5 - Asks for a
BankAccountCredentialin formatdc+sd-jwt - Requested claims:
ibanandaccount_name
Say go and I will create it.
go
Bash(credenco-cli verifier-template create-verifier-template --body @bank-account-check.json)
{
"clientId": "decentralized_identifier:did:web:wallet.acc.credenco.com:public:did:fddcd738-826f-4702-ab02-f2a5bcd97b1a",
… +67 lines (ctrl+o to expand)
Created verifier template bank-account-check. It asks holders for the iban and account_name of a BankAccountCredential and signs its requests with the wallet's default identifier. The receive can be tested now.
Note the format: in DCQL it is the OpenID4VP identifier dc+sd-jwt under DIIP_V4, DIIP_V5
and HAIP, not the Business Wallet's own SD_JWT enum. An agent that copies SD_JWT into the
query here produces a template that matches nothing, and --dry-run is where that shows up.
"Test the receive of a BankAccount credential"
verify takes the verifier template key, creates the OpenID4VP authorization request, waits for
the holder's response to be verified, and prints the claims.
Test the receive of a BankAccount credential
Bash(credenco-cli verify bank-account-check)
Scan or open:
openid4vp://authorize?client_id=decentralized_identifier%3Adid%3Aweb%3Awallet.acc.credenco.com%3Apublic%3Adid%3Afddcd738-826f-4702-ab02-f2a5bcd97b1a&request_uri=https%3A%2F%2Fwallet.acc.credenco.com%2Fpublic%2Foid4vp%2Frequest%2F08b44511-405c-4f3b-b57d-967b7fcd154c
█████████████████████████████████████████████████████████████████
█████████████████████████████████████████████████████████████████
████ ▄▄▄▄▄ ██▄▄██ █▄▄█ ▄ ▀█ ▄▄ ▄▄ █▄ ▀█ ▄▀ █▄█▄ ██ ▄▄▄▄▄ ████
████ █ █ █▄█ ▀██▄ ▄█ █▄ ▀ ██ ███ ██▄███▄▄███▄ ██ █ █ ████
████ █▄▄▄█ ██▄█▄█▄██▄▄▀█▄ █▀ ▀ ▄▄▄ ▀█ ▄▄ ▄ ▀█ ▀▄██ █▄▄▄█ ████
████▄▄▄▄▄▄▄█ ▀▄▀ ▀ ▀▄█ ▀▄█ █▄█ █▄█ █ ▀▄█ ▀▄█ █▄█ ▀▄▀▄█▄▄▄▄▄▄▄████
████▄▄ ▀ ▄▄▄▄█▄▄█▄ █▄▀ ██▄ ██▄▄▄▄▄▄█▄ ▄█▄▀▄▀ ▄▄▄▄▀▄██▄▄▀██ ▀▀████
████▀█ ▄▄▄▄ █▀▄▄▀ ▀▀█▄▄ █▄ █▀█▄▀ ▄█ ████ ▄█▄ ▀▀▀ █▀ ▄▀█▄▀▄█ ▄████
████▀█▄▄▄▄▄▄█▄█▄▄ ████ ▀█ █▄▄▄▄█▄ █▄█▄▄▄█▄▄▄▄▄▄█▀█▄█▀▄▄█ ▀████
████▀▄ ▀█▀▄ ▄ ▀▀▄ ▄█▄████▄███ ▀█▀ █▀ █▀▀▀▄█ ▀█▄▀█▀ ▄▄▄████
████▄█▄▀█ ▄█ ▀█▀▀▄ █▄ █ ▄███▄▄▄▄▄▄█▄▄▄ ▄▄ ▄▄▄▄▄█▄█▄█ ▄█ ▀████
████ ▀▀ ▄▄▀█▄▄▄█▄ █ ▄▄▄▀██▀▀▄ ▀▀▀█ ▀█▄ ▀▀▀ ▀█▄ ▀█████ ▀█▀ ████
█████ ▀▄█▄▄▄█▀██▄█▄█ █ █▀ ███ ▄▄▄ ▄ ▄▀▄█▄ ▄▄█▄ ▄ ██▄ ▀▀ ████
█████▀█ █▀▄▄ ▀ ▄█▀ ▀█▄▀ ▄ ███ █▀▄ ▀ █▄█▄▀██▀█▄▀▀ ▄▄▄▄████
█████ ▀█▄▄▄██ █ █▀ █ ██ ▀█▄▀▄ ▄██ ▄█▄█▄ ▄▄▄▄ ▄███▄▄▄▀█▀▀████
████▀ ▀ ▄▄▄ ▀▄█ ▄▄ ▄█▀▀ █▄ ▄▄▄ █ ▄█ █▀▀ ▀▄ ██ ▄▄▄ █▄ ████
████▀▄▀█ █▄█ █ █ ██ ███ ██ █▄█ █▄▄▄█ ██ ██▄▄▄▄▄ █▄█ ▀█▀ ████
████ ▀ ▄▄▄█ ███ ▄ ▄██ █▄ ▄ ▄ ▄▀▀█ ▄█▀ █▀▀ ██▄ ▄▄█▀ ████
█████▀█ ▄▀▄▄█▀▀ ▄▄█ █ ▀█ ██▀███ ▄ ▄▄ ▄ ▄ ██ ██▄ ▄██▀▄▀ ████
████ ▀▀▄ ▄▄▄█ ▀ ▄▄▀▄▄▄ ▀█▄█▄▄▄█▀▀█ █ ██▀ ▄█ ▀██▀ ██▄▀█ ██▄▄████
████▄██▄██▄▄▀▀▄▀▀ █ ▄█ ███ █ █▀█ █ ▄▄▄█▄▄ █▄ ▄██▀ ███▄▀█ ▄████
████▄ ▄▄ █▄▄▄▄█ ▄▄█ ▄█ █▄▄▄ █▀█ ▀▄██▀ ██ ▄▀▀ ██ ▀█ ██▄████
████▄█▄▄▄▄▄▀█ ▀▀▀█▄▀█ ██ ██ ▀██ ▄▄▄▀▄▀▄▀██▄▄█ ███▀ ████▀ ████
████▀▄███▀▄ ▄ ▀▄▄▄ ▄ █ ▄▄▄ █▄██ ▀ █▄ ▄█▄ ▄██ █▄█▄▄ ▄▄▄▄▄▄████
████▀█▀ ▄▀▄█▀ ▄▀ ▀▄▀█▀▄ █ ██▀ ██▄▀ ▄█ ▄█▄▄▄ ▄▄▄▄▄▀ ▄▄██▀█▄ ████
████ ▀ ▀▀▄▄ ▀▀▄█ ▀███▀███ █ █▄▄ ▄ ▀██ ▄ █▄ ▄▀██▄ ▄█▄▄▀▄████
██████████▄█ ▄▄▀▀▀█ ▄█ ██ ▄▄▄ █▄ █▄▄▄██ ▄█▄ ██▀ ▄▄▄ █▀ ████
████ ▄▄▄▄▄ █ █ ▄ ▀█▄▀▄▄▄▀██▄▀ █▄█ ▀█▀ █▄ ▀█▀▀ ▀█▀ █▄█ ▄▄ ████
████ █ █ █▄ █▄▄ █ █ ███ ▀█ ▄ ▄▄▄██▄ █▄▄ ▄█ ▄███ ▄█ ▄████
████ █▄▄▄█ █ ▀▀ ▀█▀▄▀██ ▄█▄█▄▄▄▄█▄ ▀▄▄▀▄█ ▀▄█▄ ██▀▄ ▄ ▄▀▄████
████▄▄▄▄▄▄▄█▄▄█▄▄█▄██▄▄██▄▄██▄▄█████▄█▄█▄█▄█▄█▄▄▄██▄▄▄█▄█▄█▄▄████
█████████████████████████████████████████████████████████████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
status: authorization_request_created
status: authorization_response_verified
{
"correlation_id": "93b42470-0a64-4ef5-a96a-bc96eb19db8b",
… +21 lines (ctrl+o to expand)
Verified. The holder disclosed exactly the requested claims:
| Claim | Value |
|---|---|
iban | NL91ABNA0417164300 |
account_name | Ada Lovelace |
currency and account_type stayed hidden.
currency and account_type are absent even though the credential carries them, because the DCQL
query asked for iban and account_name and selective disclosure kept the rest hidden. That is
the result an agent should check: not "the command exited 0", but "the claims I asked for are in
verified_data.credential_claims, and nothing else is".
Of the five verification statuses, only authorization_response_verified has verified_data.
An agent that treats the first poll as the answer gets authorization_request_created and no
claims at all, and would report a success that proved nothing. verify waits for the verified
status for exactly this reason; if you poll
credenco-cli universal-oidc4-vp get-oid4vp-request-status yourself, wait for it too.
A prompt that works
Nothing here needs a custom tool definition. Pointing the agent at the binary is enough:
You have `credenco-cli` on your PATH and a logged-in profile for the Business Wallet.
- Run `credenco-cli operations` and `credenco-cli <command> --help` to find out what exists. Never guess a flag or a field name.
- An API call writes JSON to standard output, because you are not a terminal. Parse it. Progress messages, QR codes and errors are on standard error. `operations`, `profile list` and `--help` are plain text instead: read them, do not parse them.
- Branch on the exit code, not on the message: 1 local failure, 2 usage or configuration, 3 authentication, 4 not found, 5 server error, 6 other API error.
- Before anything that creates, changes or deletes, run the command with `--dry-run`, show me the request, and wait for me to say go.
- Never pass a secret as a flag. The stored profile already holds the credentials.
- Never add `--yes` without asking me first.
Setup
Run credenco-cli login once yourself. It stores the host, the credentials and the default wallet
in a profile, and the agent uses that profile without having to handle the secret. See
Profiles.
$ credenco-cli login wallet.acc.credenco.com
An API key is bound to one wallet, so start the agent on a sandbox wallet. See API Keys.
Next
- Usage examples is the same walkthrough with every step spelled out.
- The credenco-cli introduction covers installation, profiles, output formats and the full exit-code table.