The Agent is the base component to use in Aries Framework JavaScript. It builds on the concept of an agent as described in Aries RFC 0004: Agents.
Before initializing your agent, make sure you have followed the setup guide for your platform and environment:
Note: This setup is assumed for a react native mobile agent Other platforms: To do
You can set up an agent by importing the Agent
class. It requires you to pass in a JSON object to configure the agent. The following is an example with only the required configuration options specified. The agent by itself can't do much yet, we need transports to be able to interact with other agents.
import { Agent, InitConfig } from '@aries-framework/core'
import { agentDependencies } from '@aries-framework/node'
const agentConfig: InitConfig = {
// The label is used for communication with other agents
label: 'My Agent',
walletConfig: {
id: 'walletId',
key: 'testKey0000000000000000000000000',
},
}
const agent = new Agent(agentConfig, agentDependencies)
This is the optimal initialization code for a scenario where complete functionality is needed. We will walk through the following steps to initialize the agent with full capabilities.
import {
Agent,
AutoAcceptCredential,
ConnectionEventTypes,
ConnectionInvitationMessage,
ConnectionRecord,
ConnectionStateChangedEvent,
ConsoleLogger,
CredentialEventTypes,
CredentialRecord,
CredentialState,
CredentialStateChangedEvent,
HttpOutboundTransport,
InitConfig,
LogLevel,
} from '@aries-framework/core'
import { agentDependencies } from '@aries-framework/react-native'
You will need the genesis file of the Indy ledger you are connecting to, to issue, accept, prove, and verify credentials. For example, lets say your agent will need to accept a verifiable credential from trinsic.id, you will probably need to download the genesis file for the Sovrin network.
More to find here
Other
Example: DTS Verifiable Credential Issuer Service Corresponding genesis file: http://test.bcovrin.vonx.io/genesis
Sample initialization code
const BCOVRIN_TEST_GENESIS = `{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node1","blskey":"4N8aUNHSgjQVgkpm8nhNEfDf6txHznoYREg9kirmJrkivgL4oSEimFF6nsQ6M41QvhM2Z33nves5vfSn9n1UwNFJBYtWVnHYMATn76vLuL3zU88KyeAYcHfsih3He6UHcXDxcaecHVz6jhCYz1P2UZn2bDVruL5wXpehgBfBaLKm3Ba","blskey_pop":"RahHYiCvoNCtPTrVtP7nMC5eTYrsUA8WjXbdhNc8debh1agE9bGiJxWBXYNFbnJXoXhWFMvyqhqhRoq737YQemH5ik9oL7R4NTTCz2LEZhkgLJzB3QRQqJyBNyv7acbdHrAT8nQ9UkLbaVL9NBpnWXBTw4LEMePaSHEw66RzPNdAX1","client_ip":"138.197.138.255","client_port":9702,"node_ip":"138.197.138.255","node_port":9701,"services":["VALIDATOR"]},"dest":"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv"},"metadata":{"from":"Th7MpTaRZVRYnPiabds81Y"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node2","blskey":"37rAPpXVoxzKhz7d9gkUe52XuXryuLXoM6P6LbWDB7LSbG62Lsb33sfG7zqS8TK1MXwuCHj1FKNzVpsnafmqLG1vXN88rt38mNFs9TENzm4QHdBzsvCuoBnPH7rpYYDo9DZNJePaDvRvqJKByCabubJz3XXKbEeshzpz4Ma5QYpJqjk","blskey_pop":"Qr658mWZ2YC8JXGXwMDQTzuZCWF7NK9EwxphGmcBvCh6ybUuLxbG65nsX4JvD4SPNtkJ2w9ug1yLTj6fgmuDg41TgECXjLCij3RMsV8CwewBVgVN67wsA45DFWvqvLtu4rjNnE9JbdFTc1Z4WCPA3Xan44K1HoHAq9EVeaRYs8zoF5","client_ip":"138.197.138.255","client_port":9704,"node_ip":"138.197.138.255","node_port":9703,"services":["VALIDATOR"]},"dest":"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb"},"metadata":{"from":"EbP4aYNeTHL6q385GuVpRV"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node3","blskey":"3WFpdbg7C5cnLYZwFZevJqhubkFALBfCBBok15GdrKMUhUjGsk3jV6QKj6MZgEubF7oqCafxNdkm7eswgA4sdKTRc82tLGzZBd6vNqU8dupzup6uYUf32KTHTPQbuUM8Yk4QFXjEf2Usu2TJcNkdgpyeUSX42u5LqdDDpNSWUK5deC5","blskey_pop":"QwDeb2CkNSx6r8QC8vGQK3GRv7Yndn84TGNijX8YXHPiagXajyfTjoR87rXUu4G4QLk2cF8NNyqWiYMus1623dELWwx57rLCFqGh7N4ZRbGDRP4fnVcaKg1BcUxQ866Ven4gw8y4N56S5HzxXNBZtLYmhGHvDtk6PFkFwCvxYrNYjh","client_ip":"138.197.138.255","client_port":9706,"node_ip":"138.197.138.255","node_port":9705,"services":["VALIDATOR"]},"dest":"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya"},"metadata":{"from":"4cU41vWW82ArfxJxHkzXPG"},"type":"0"},"txnMetadata":{"seqNo":3,"txnId":"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node4","blskey":"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw","blskey_pop":"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP","client_ip":"138.197.138.255","client_port":9708,"node_ip":"138.197.138.255","node_port":9707,"services":["VALIDATOR"]},"dest":"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA"},"metadata":{"from":"TWwCRQRZ2ZHMJFn9TzLp7W"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008"},"ver":"1"}`
const agentConfig = {
indyLedgers: [
{
id: 'BCovrin Test',
genesisTransactions: BCOVRIN_TEST_GENESIS,
isProduction: false,
},
],
}
Note: You do not need the genesis file if you are creating a connection between your Agent and another Agent for exchanging simple messages.
Mediators (Routing Agents) are Agents that serve as intermediaries to facilitate the flow of messages between other types of agents. You will need a mediator Agent if you are going to deal with VC (Verifiable Credentials), however, you can ignore the mediator step if you are creating an Agent for the sole purpose of exchanging messages with another Agent.
Example: If you are testing VC related functionality and need a mediator, you can use the Animo Public Mediator.
- Head to Animo Public Mediator.
- Copy mediator invite url and save it (i.e. MEDIATOR_INVITE = "url").
Other alternatives:
More about Mediators.
const agentConfig: InitConfig = {
label: 'My Agent',
mediatorConnectionsInvite: MEDIATOR_INVITE,
walletConfig: {
id: 'WalletId',
key: 'TestKey',
},
autoAcceptConnections: true,
autoAcceptCredentials: AutoAcceptCredential.ContentApproved,
autoAcceptProofs: AutoAcceptProof.ContentApproved,
indyLedgers: [
{
id: 'BCovrin Test',
genesisTransactions: BCOVRIN_TEST_GENESIS,
isProduction: false,
},
],
logger: new ConsoleLogger(LogLevel.info),
}
const agent = new Agent(agentConfig, agentDependencies)
After creating the Agent object, we need to create and set the Inbound/Outbound transports that will handle traffic to/from the Agent.
const httpOutboundTransporter = new HttpOutboundTransporter()
agent.registerOutboundTransport(httpOutboundTransporter)
// Inbound transports are currently built-in, you don't need to create them.
More about Transports.
After creating the Agent object and configuring it, we initialize the Agent.
// It's highly recommended to wrap the initialization flow in a try/catch block
try {
await agent.initialize()
console.log('Initialized agent!')
} catch (e) {
console.log(`Agent init error:${e}`)
}
After you successfully initialize your Agent, you will notice that most of the hard work is being done by the underlying Aries/Indy framework. However, you as a controller will need to intercept in some situations when there is a state change (like when you need to accept an offered credential or reject/accept an incoming connection request). This is done through state change handlers.
agent.events.on<AgentMessageReceivedEvent>(AgentEventTypes.AgentMessageReceived, handleBasicMessageReceive)
agent.events.on<CredentialStateChangedEvent>(
CredentialEventTypes.CredentialStateChanged,
// Custom callback for handling any state change when offering/receiving VCs
handleCredentialStateChange
)
agent.events.on<ConnectionStateChangedEvent>(
ConnectionEventTypes.ConnectionStateChanged,
// Custom callback for handling any state change when offering/receiving a connection
handleConnectionStateChange(event)
)
Example: This sample credential callback shows how to detect that a credential is received, show the user the credential asserts and give the option to accept/reject the offered credential.
const handleCredentialStateChange = async (event: CredentialStateChangedEvent) => {
console.log(
`>> Credential state changed: ${event.payload.credentialRecord.id}, previous state -> ${event.payload.previousState} new state: ${event.payload.credentialRecord.state}`
)
if (event.payload.credentialRecord.state === CredentialState.OfferReceived) {
console.log(`>> Received offer, should display credential to user`)
// Display offer to user
// On user click "Accept"
console.log(`>>ACCEPTING OFFER`)
agent.credentials.acceptOffer(event.payload.credentialRecord.id)
} else if (event.payload.credentialRecord.state === CredentialState.Done) {
Alert.alert('Credential Saved')
}
}
More about Credentials. See Overview for more information on how event handlers work.
Thats it, you are good to go with the Agent.
The agent currently supports the following configuration options. Fields marked with a * are required. Other parts of this documentation go into more depth on the different configuration options.
label
*: The label to use for invitations.walletConfig
: The wallet config to use for creating and unlocking the wallet. Not required, but requires extra setup if not passed in constructorendpoint
: The endpoint (schema + host + port) to use for invitations.publicDidSeed
: The seed to use for initializing the public did of the agent. This does not register the DID on the ledger.genesisPath
: The path to the genesis file to use for connecting to an Indy ledger.genesisTransactions
: String of genesis transactions to use for connecting to an Indy ledger.indyLedgers
: The indy ledgers to connect to. This is an array of objects with the following properties. EithergenesisPath
orgenesisTransactions
must be set, but not both. See 4. Ledger for more information.id
*: The id (or name) of the ledger, also used as the pool nameisProduction
*: Whether the ledger is a production ledger. This is used by the pool selector algorithm to know which ledger to use for certain interactions (i.e. prefer production ledgers over non-production ledgers)genesisPath
: The path to the genesis file to use for connecting to an Indy ledger.genesisTransactions
: String of genesis transactions to use for connecting to an Indy ledger.
logger
: The logger instance to use. Must implementLogger
interfacedidCommMimeType
: The mime-type to use for sending and receiving messages.DidCommMimeType.V0
: "application/ssi-agent-wire"DidCommMimeType.V1
: "application/didcomm-envelope-enc"
autoAcceptMediationRequests
- As a mediator, whether to auto accept mediation requests. If not enabled requests should be accepted manually on the mediator modulemediationConnectionsInvitation
- Connection invitation to use for default mediator. If specified the agent will create a connection, request mediation and store the mediator as default for all connections.defaultMediatorId
- Mediator id to use as default mediator. Use this if you want to override the currently default mediator.clearDefaultMediator
- Will clear the default mediatorautoAcceptConnections
: Whether to auto accept all incoming connections. Default falseautoAcceptProofs
: Whether to auto accept all incoming proofs:AutoAcceptProof.Always
: Always auto accepts the proof no matter if it changed in subsequent stepsAutoAcceptProof.ContentApproved
: Needs one acceptation and the rest will be automated if nothing changesAutoAcceptProof.Never
: Default. Never auto accept a proof
autoAcceptCredentials
: Whether to auto accept all incoming proofs:AutoAcceptCredential.Always
: Always auto accepts the credential no matter if it changed in subsequent stepsAutoAcceptCredential.ContentApproved
: Needs one acceptation and the rest will be automated if nothing changesAutoAcceptCredential.Never
: Default. Never auto accept a credential