A fast and minimal framework for building agent-integrated systems
Project description
Summary
agency
is a python library that provides a minimal framework for creating
agent-integrated systems.
The library provides a simple foundation for connecting agents, software systems, and human users by defining actions, callbacks, and access policies that you can use to connect, monitor, and interact with your agents.
agency
handles the communication details and allows discovering and invoking
actions across parties, automatically handling things such as reporting
exceptions, enforcing access restrictions, and more.
Features
Low-Level API Flexibility
- Straightforward class/method based agent and action definition
- Supports defining single process applications or networked agent systems using AMQP
Observability and Control
- Before/after action and lifecycle callbacks for observability or other needs
- Access policies and permission callbacks for access control
Performance and Scalability
- Multithreaded (though python's GIL is a bottleneck for single process apps)
- AMQP support for multiprocess and networked systems (avoids GIL)
- Python multiprocess support is planned for better scalability on single-host systems
- Decentralized networking support planned
Multimodal support
- In development, though a timeline of features is not yet determined.
Full demo available at examples/demo
- Two OpenAI agent examples
- HuggingFace transformers agent example
- Simple Flask/React web interface included
- Operating system access for agents
- Docker configuration for reference and development
(Please note that a Gradio UI is being developed to replace the Flask/React app above)
API Overview
agency
is an implementation of the Actor
model for building AI agent
integrated systems.
In agency
, all entities are represented as instances of the Agent
class.
This includes all humans, software, and AI-driven agents that may communicate as
part of your application.
All agents may expose "actions" that other agents can discover and invoke at run time. An example of a simple agent implemention could be:
class CalculatorAgent(Agent):
def _action__add(a, b):
return a + b
This defines an agent with a single action: "add"
. Other agents will be able
to call this method by sending a message to an instance of CalculatorAgent
and
specifying the "add"
action.
other_agent._send({
'to': 'CalcAgent',
'thoughts': 'Optionally explain here',
'action': 'add',
'args': {
'a': 1,
'b': 2,
},
})
Actions must also specify an access policy, allowing you to control access for safety. For example:
@access_policy(ACCESS_PERMITTED) # This allows the action at any time
def _action__add(a, b):
...
You can also define callbacks for various purposes:
class CalculatorAgent(Agent):
...
def _before_action(self, original_message: dict):
# Called before any action is attempted
def _after_action(self, original_message: dict, return_value: str, error: str):
# Called after any action is attempted
def _after_add(self):
# Called after the agent is added to the space and may begin communicating
def _before_remove(self):
# Called before the agent is removed from the space
def _request_permission(self, proposed_message: dict) -> bool:
# Called before an ACCESS_REQUESTED action is attempted for run-time review
A Space
is how you connect your agents together. An agent cannot communicate
with others until it is added to a common Space
.
There are two included Space
implementations to choose from:
NativeSpace
- which connects agents within the same python processAMQPSpace
- which connects agents across processes and systems using an AMQP server like RabbitMQ.
Here is an example of creating a NativeSpace
and adding two agents to it.
space = NativeSpace()
space.add(CalculatorAgent("CalcAgent"))
space.add(AIAgent("AIAgent"))
# The agents above can now communicate
These are just some of the main agency
features. For more detailed information
please see the docs directory.
Install
pip install agency
or
poetry add agency
Running the Demo Application
(Note: a Gradio app is being developed to replace the following UI soon.)
To run the demo, please follow the directions at
examples/demo. After a short boot time you can visit the
web app at http://localhost:8080
and you should see a simple chat interface.
The following is a screenshot of the web UI that demonstrates multiple demo agents interacting and following orders.
The screenshot also demonstrates the results of rejecting an action and
directing an agent to use a different approach in real time. After I explained
my rejection of the read_file
action (which happened behind the scenes on the
terminal), "FunctionAI"
appropriately used the shell_command
action with wc -l Dockerfile
.
FAQ
How does agency
compare to other agent libraries?
Though you could entirely create a simple agent using only the primitives in
agency
(see examples/demo/agents/
), it is not
intended to be an agent toolset like other libraries. For example, you won't
find much support for building prompts or working with vector databases, etc.
Implementation of agent behavior is left up to you.
agency
is concerned with providing a minimal communication and control
foundation on which to define and integrate agent systems in a performant
and flexible way, allowing developers to create custom agent solutions as
they see fit.
So if you're looking for a library with just enough structure to build from
but not so much that it gets in your way, then agency
might be for you.
What are some known limitations or issues?
-
agency
is still in early development. Like many projects in the AI agent space it is somewhat experimental at this time, with the goal of finding and providing a minimal yet useful foundation for building agent systems.Expect changes to the API over time as features are added or changed. The library follows semver versioning starting at 1.x.x. Minor version updates may contain breaking API changes. Patch versions should not.
-
This library makes use of threads for each individual agent. Multithreading is limited by python's GIL, meaning that if you run a local model or other heavy computation in the same process as other agents, they may have to wait for their "turn". Note that I/O does not block, so networked backends or services will execute in parallel.
For blocking processes, it's recommended to use the
AMQPSpace
class and run heavy computations in isolation to avoid blocking other agents. Multiprocessing support is also planned as another option for avoiding the GIL. -
This API does not assume or enforce predefined roles like "user", "system", "assistant", etc. This is an intentional decision and is not likely to change.
agency
is intended to allow potentially large numbers of agents, systems, and people to come together. A small predefined set of roles gets in the way of representing many things generally. This is a core design feature ofagency
: that all entities are represented similarly and may be interacted with through common means.The lack of roles may require extra work when integrating with role based APIs. See the implementation of
OpenAIFunctionAgent
for an example. -
There is currently not much by way of storage support. That is mostly left up to you and I'd suggest looking at the many technologies that focus on that. The
Agent
class implements a simple_message_log
array which you can make use of or overwrite to back it with longer term storage. More direct support for storage APIs will likely be considered in the future.
Contributing
Please do!
Development Installation
git clone git@github.com:operand/agency.git
cd agency
poetry install
Developing with the Demo Application
See the demo directory for instructions on how to run the demo.
The demo application is written to showcase both native and AMQP spaces and several agent examples. It can also be used for experimentation and development.
The application is configured to read the agency library source when running, allowing changes to be tested manually.
Test Suite
Ensure you have Docker installed. A small RabbitMQ container will be automatically created.
You can run the test suite with:
poetry run pytest
Roadmap
-
Multimodal Support: Multimedia transfer for use with multimodal models or other multimedia services.
-
Multiprocess Support: An additional
Space
type utilizing python multiprocessing, as another parallelism option for single-host systems. -
Storage Support Durable session support will be included. Other forms of storage will be considered though it's not clear yet what that may look like.
-
Gradio Application The current demo application uses a proof-of-concept quality Flask/React web app. A Gradio application will be developed to replace the Flask app and serve as a reference example that can be extended or modified.
-
Decentralized Networking An additional
Space
type using decentralized protocols, enabling the highest levels of scalability and opening the door for peer-to-peer agent networks. -
More Examples: More examples of integrations with popular AI libraries and services will be added.
Planned Work
If you have any suggestions or otherwise, feel free to add an issue!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.