Package: aries-staticagent
Static Agent LibraryThis repo contains an example Aries Static Agent Library in Python.A static agent is a form of agent that can speak DIDComm at a basic level but its keys and
connections are configured statically. Static Agents have a direct relationship with a single full
agent. Static Agents do not have a wallet.Examples of static agents may include:Remote administration interface for an agentIoT devicesRelaysOpenAPI to DIDComm translatorA static agent's configuration minimally consists of:Its own public and private keyThe public key of its full agent counterpartThe endpoint of its full agent counterpartIt is up to you to secure your static agent's configuration.The examples included in this
repository use command line arguments or environment variables to configure the agent for simplicity
and demonstration purposes only.This is not recommended for production environments.This library makes as few assumptions about it's running environment as possible. This includes
few dependencies, assumptions about web frameworks, etc.Quick Start GuideRequirementsPython 3.6 or higherRunning the included examplesYou will need to pair the static agent with a full agent capable of basic DIDComm to complete the
examples. TheIndy Python Reference Agentcan be used as the full agent for these examples.Create and activate python virtual environment:$python3-mvenvenv
$sourceenv/bin/activateInstall dependencies and the library into the virtual environment:$pipinstall-e.If you want to run the included tests, install thetestfeature with pip:pip install -e .[test]Executekeygen():$python-c"import aries_staticagent; aries_staticagent.keygen()"Forfullagent:DID:<Base58encodedDID>VK:<Base58encodedverkey>

Forstaticagent:VK:<thesameBase58encodedverkey>SK:<Base58encodedsigkey>As the output implies, the first section is intended to be entered in on the full agent to configure
a static connection. The second section is used to configure the static agent. Theverkey(VK) in
the first and second section are thesamekey, representing the key the static agent will use
for the connection. Thekeygenscript doesnotgenerate the keys that the full agent will use.If using theIndy Python Reference Agent, open the web interface and
clickAdd Static Connection. Enter the information output bykeygen.pyand a label of your
choice. The endpoint of the static agent is optional and must match the hostname and port you
configure for the static agent if running the web server example. After clickingAdd, a new
dialogue window will open with the information needed to now start up the static agent.If you are using another agent that supports configuring a static connection, follow the
instructions provided by that agent.Start the static agent (in this case,exapmles/cron.py):$pythonexamples/cron.py--endpoint<theendpointofthefullagent>\$--endpointkey<theverkeyoutputbythefullagent>\$--mypublickey<theverkeyoutputbykeygen.py>\$--myprivatekey<thesigkeyoutputbykeygen.py>In the full agent's BasicMessages, you should now see a message sent from the static agent script.TODO: Include screencast of running the example with the Indy Python Reference AgentUsing the libraryRefer to theexamplesdirectory for complete working examples of using this library.Setting up a Static Agent Connectionfromaries_staticagentimportStaticConnection# endpoint, endpointkey, mypublickey, myprivatekey key are obtained through some form of static# configurationconn=StaticConnection((mypublickey,myprivatekey),their_vk=endpointkey,endpoint=endpoint)This will open a static connection with the full agent reachable atendpointand messages packed
forendpointkey.Sending a message to the Full AgentWith the static agent connectiona, to send messages to the full agent:conn.send({"@type":"https://didcomm.org/basicmessage/1.0/message","~l10n":{"locale":"en"},"sent_time":utils.timestamp(),"content":"The Cron Script has been executed."})An asynchronous method is also provided:awaitconn.send_async({"@type":"https://didcomm.org/basicmessage/1.0/message","~l10n":{"locale":"en"},"sent_time":utils.timestamp(),"content":"The Cron Script has been executed."})Receiving messages from the Full AgentTransport mechanisms are completely decoupled from the Static Agent Library. This is intended to
allow library consumers to choose which transport is appropriate for their use case. Theexamples/webserver_aiohttp.pyexample shows how one might use theaiohttplibrary as an inbound
transport mechanism for the static agent:fromaiohttpimportwebfromaries_staticagentimportStaticConnection,utils# ... Configuration omitted# Create static agent connectionconn=StaticConnection((args.mypublickey,args.myprivatekey),their_vk=args.endpointkey,endpoint=args.endpoint)# Register a handler for the basicmessage/1.0/message message type@conn.route("https://didcomm.org/basicmessage/1.0/message")asyncdefbasic_message(msg,conn):# Respond to the received basic message by sending another basic message backawaitconn.send_async({"@type":"https://didcomm.org/basicmessage/1.0/message","~l10n":{"locale":"en"},"sent_time":utils.timestamp(),"content":"You said:{}".format(msg['content'])})# aiohttp request handlerasyncdefhandle(request):# Read request body and pass to StaticConnection.handleawaitconn.handle(awaitrequest.read())raiseweb.HTTPAccepted()# Register aiohttp request handlerapp=web.Application()app.add_routes([web.post('/',handle)])# Start the web serverweb.run_app(app,port=args.port)As seen in this example, registering a handler for a DIDComm message is done using the@conn.route('<message_type>')decorator. Passing raw, unpackaged messages to the static agent
connection over the decoupled transport mechanism is done by callingconn.handle(<raw message>).Static agents can only unpack messages sent by the full agent.Unresolved QuestionsAre we allowing Agent routing between a static agent and it's full agent?We're starting with no and will revisit in the future.