ACA-Py Plugins
June 22, 2026 · View on GitHub
This repository contains approved and tested plugins for ACA-Py. This is to encourage collaboration and sharing of useful features not directly included in ACA-Py.
Developer Notes
The easiest way to develop and test ACA-Py plugins is to use the DevContainer configured in this repository.
- Open devcontainer in VS Code
- Python and all dependencies will be loaded
- Poetry will be loaded and configured, dependencies will be installed
- Docker and Docker Compose will be available
Repo Management Script
A script was developed to help with maintenance of the repo called repo_manager.py. To run it you need a current version of poetry and python available.
Run python repo_manager.py and you will be met with a number of options. Run the options as needed.
- (1) Is used for starting or adding a new plugin. It will generate all the common scaffolding for a plugin which has the expected format.
- (2) Is used for updating and changing common poetry dependencies and
configurations. It takes the poetry sections in the
pyproject.tomlfiles from theplugin_globalsdirectory and combines them with the local plugin poetry sections. For the dependencies the common will be overridden by the globals. The other config sections will be replaced by the global configs. Then the lock files will be removed and re-installed. - (3) Is used for updating the plugin versions in the
plugin_globalsdirectory. It will update the versions of the plugins in theplugin_globalsdirectory to the latest version on the main branch of the plugin repo. It will also update theplugin_globalsdirectory to the latest version on the main branch of the plugin repo. - (4) This option is used by the CI/CD release pipeline. It updates the release notes and the individual plugins with a new version of ACA-Py.
- (5) This option is also used by the CI/CD release pipeline. It gets any plugins that have succeeded the tests after a new version of ACA-Py has been released if their changes were not reverted than the plugin has been updated to the new version of ACA-Py.
- (6) This option will run a general update for all poetry lock files in all plugins. THIS OPTION IS NOT CURRENTLY WORKING PROPERLY AND SHOULD BE USED WITH CAUTION.
- (7) This option is used for upgrading a particular library for all plugins. It's useful for when you don't want to do a general upgrade for every library.
- (8) This option is used for closing a range of PR's that are related to the same shared dependency update. You use the lower and upper bounds of the PR numbers to close all the related PR's. This is useful for keeping the repo clean and reducing the number of PR's that need to be reviewed. You can included PR numbers which have already been merged or closed and the script will skip them. You should be careful when using this option as it will close all PR's in the range regardless of their status. Make sure to double check the PR numbers before running this option. If you do accidentally close a PR that shouldn't be closed, you can always reopen it.
- (9) This option finds open Dependabot PRs that update a
pyproject.tomlversion constraint (rather than just apoetry.lockentry), extracts each change, and reports which localpyproject.tomlfiles still carry the old version or a different version. Pass--applyon the command line (python repo_manager.py 9 --apply) to have the script update the exact-match files in place and regenerate theirpoetry.lockfiles automatically. Files flagged as having a different version are listed for manual review but are never modified automatically.
Dependabot Management
Currently dependabot is configured to manage plugin dependencies individually. This is fine for libraries which aren't shared across plugins but will create numerous PR's for plugins that share dependencies. Here is the current strategy for applying the dependabot updates on a weekly basis without having to update/approve/merge each PR individually:
-
Update the
mainbranch in your fork to the latest and create a "weekly update" branch. -
Run option (7) without arguments to preview which libraries have open Dependabot PRs (use
--debugfor full per-PR detail):python repo_manager.py 7 python repo_manager.py 7 --debugReview the list. When it looks correct, re-run with
--applyto update allpoetry.lockfiles across all plugins:python repo_manager.py 7 --applyOption (7) queries open Dependabot PRs to determine which libraries need updating, then searches each
poetry.lockand runspoetry update --lock <package>in every directory that contains the package. It handles Poetry's internal hyphen-to-underscore normalisation automatically. It only updates lock files — it does not modifypyproject.toml. -
Run option (9) to check whether any Dependabot PRs required a
pyproject.tomlversion-constraint change that option (7) cannot make:python repo_manager.py 9Review the output. If files are listed under "Needs update", re-run with
--applyto update thosepyproject.tomlfiles and regenerate their lock files automatically:python repo_manager.py 9 --applyFiles listed under "Has a different version" require manual review and editing — inspect the constraint and decide whether it needs updating before committing.
-
Submit the result as the "weekly update" PR, with all updates included in the same PR. Call the PR by the current date, e.g.
Weekly Update - YYYYMMDD -
If the PR's integration tests fail, a library update has likely broken something in one or more plugins. Investigate the failure (the CI logs and an AI assistant are both useful here) to identify which package is responsible. Back out only the affected
poetry.lockchange(s) — restore the previous lock entry for that package — and push the correction to the same branch. Once the remaining updates pass and the PR is merged, the Dependabot PR(s) for the backed-out package(s) will not be closed automatically. Follow up on those using the instructions in the section below. -
Once the weekly update PR is merged, Dependabot will automatically close the PRs it opened that are no longer needed. Do not close those PRs manually — let the automation handle it.
Following up on PRs not closed automatically
After the weekly update PR is merged and you receive the "close" messages, check for any Dependabot PRs that were not closed automatically:
python repo_manager.py 7 --debug
A PR that remains open after the merge means one of the following:
- The version it targets is still not satisfied by the updated constraints — option (9) "Has a different version" output is the first place to look.
- The update was backed out of the weekly PR because it broke integration tests
(see step 6 above). In this case the library upgrade is valid but requires a
code change in the affected plugin(s) alongside it. Investigate the failure,
fix the plugin code, and submit a separate follow-up PR that includes both the
poetry.lockupdate and the code fix together. - The PR covers a plugin or dependency that is intentionally pinned and should not be updated at this time — in that case, leave the PR open or close it deliberately after confirming with the team.
Each remaining PR must be reviewed and resolved individually before it can be considered handled.
Lite plugins
Sometimes is desirable to have a plugin that doesn't need integration tests or
extra scaffolding. However, we need a way to avoid these plugins running
integration tests in the CI/CD pipeline. To do this, we can simply add the
plugin name to the lite_plugins file, a line-separated list of plugin names.
Plugin Documentation
Plugin developers SHOULD describe what the plugin does, any limitations (ex only in multitenant mode), any known issues interacting with other plugins, etc. Full documentation including a plugin_config sample should be provided.
This documentation should be provided in your plugin root as a README.md file,
with at least a Description and Configuration section.
Build and Run
Each plugin (that is not a Lite Plugin) MUST include a Dockerfile (such as Dockerfile) to run integration tests. This image is not intended for production as it copies the plugin source and loads its dependencies (including ACA-Py) along with a simplistic ACA-Py configuration file, (such as default.yml).
Run and Debug
In the devcontainer, we can run an ACA-Py instance with our plugin source loaded
and set breakpoints for debug (see launch.json).
To run your ACA-Py code in debug mode, go to the Run and Debug view, select
"Run/Debug Plugin" and click Start Debugging (F5). Using the default.yml for
the plugin (such as default.yml),
your agent swagger is available at http://localhost:3001/api/doc.
Testing
For the plugin to be accepted into this repo it must have adequate testing.
Unit Testing:
- There should be adequate unit testing coverage. A coverage report is created when
poetry run pytest .in ran from the devcontainer. A good mark to aim for is 90% but the quality of the tests on critical sections is more important than coverage percentage. - Mocking can be challenging. Study the existing plugins in this repo and ACA-Py in general for good examples of mocks and fixtures.
- Put your unit tests in a tests folder in your plugin version path and name all files and test with the
test_prefix.
Integration Testing:
- Plugins SHOULD have a suite of integration tests. The base suite will be created for your plugin after running the updater script. Plugins that don't have integrations must be flagged as being a Lite Plugin.
- An Integration
README(such as integration tests) SHOULD describe the set of integration tests. When you generate a new plugin, you should have everything you need to start integration testing and a sample test will be provided.
Deploy
For production use, plugins should be installed as libraries to an ACA-Py image.
This requires having a Dockerfile and a config file for your agent.
Example Dockerfile:
FROM ghcr.io/openwallet-foundation/acapy:py3.12-1.1.0
USER root
# install plugins as binaries
RUN pip install git+https://github.com/openwallet-foundation/acapy-plugins@main#subdirectory=basicmessage_storage
RUN pip install git+https://github.com/openwallet-foundation/acapy-plugins@main#subdirectory=connection_update
USER $user
COPY ./configs configs
CMD ["ACA-Py"]
Example config file (local single tenant):
label: plugins-agent
admin-insecure-mode: true
admin: [0.0.0.0, 9061]
inbound-transport:
- [http, 0.0.0.0, 9060]
outbound-transport: http
endpoint: http://host.docker.internal:9060
genesis-url: http://test.bcovrin.vonx.io/genesis
emit-new-didcomm-prefix: true
wallet-type: askar
wallet-storage-type: default
auto-provision: true
debug-connections: true
auto-accept-invites: true
auto-accept-requests: true
auto-ping-connection: true
auto-respond-messages: true
log-level: info
plugin:
- basicmessage_storage.v1_0
- connection_update.v1_0
Now you can deploy a agent with as many plugins as you want as long as they are declared in your build config file and installed.
docker build -f <Dockerfile> --tag acapy_plugins .
docker run -it -p 9060:9060 -p 9061:9061 --rm acapy_plugins start --arg-file=<config-file> -->