Skip to main content

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:

ClaimValue
ibanNL91ABNA0417164300
account_nameAda Lovelace
currencyEUR
account_typechecking

"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:

AttributeMandatorySelectively disclosable
ibanyesyes
account_nameyesyes
currencynoyes
account_typenoyes

The response echoes the stored template, so the agent can confirm the four claims landed in order rather than assuming they did.

Ask the agent to preview first

--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_completed once a wallet accepts the offer. An agent working unattended should pass --wait=false, hand the request_uri to whoever is holding the phone, and poll credenco-cli issue-credential get-credential-issuance-status <correlation_id> afterwards.
  • awaiting_confirmation is 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 profile DIIP_V5
  • Asks for a BankAccountCredential in format dc+sd-jwt
  • Requested claims: iban and account_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:

ClaimValue
ibanNL91ABNA0417164300
account_nameAda 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".

Only one status carries the claims

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​