A Python library for processing Activity Streams 2.0 activities via a rule-based engine. Activity Bus is designed to work in concert with Activity Store and provides a high-level pipeline for submitting, validating, storing, and processing activities using dynamic, declarative behaviors.
pip install activity-bus- Build on Activity Store for storage, caching, and dereferencing
- Easy creation and management of behaviors
- Clean, async-first interface
- Compatible with ActivityPub delivery semantics
- Agent-friendly, auditable, and introspectable
- Support for asynchronous and dynamic rule processing
import asyncio
from activity_bus import ActivityBus, when
# Define a behavior
@when({"type": "Create", "object": {"type": "Note"}})
def create_note(activity):
print(f"Note created with content: {activity['object']['content']}")
# You can return new activities to be submitted
return [{
"type": "Notification",
"summary": "New note created",
"actor": activity["actor"]
}]
async def main():
# Create a new ActivityBus instance
bus = ActivityBus()
# Submit an activity
activity = {
"type": "Create",
"actor": "https://example.com/users/user1",
"object": {
"type": "Note",
"content": "Hello, world!"
}
}
await bus.submit(activity)
# Process the next activity in the queue
processed = await bus.process_next()
# Process any new activities that were created
notification = await bus.process_next()
print(f"Processed: {processed}")
print(f"Notification: {notification}")
# Run the example
asyncio.run(main())- Must contain at minimum:
actor,type, and optionallyid - If
idis not present, it is generated:/users/<user-id>/outbox/<nanoid> - Must be scoped under actor's URI; otherwise, rejected
- On submission,
publishedtimestamp is set
await bus.submit(activity)- Validate required fields
- Set ID if missing
- Validate ID scope
- Store activity in ActivityStore
- Enqueue activity in in-memory asyncio.Queue
await bus.process_next()- Dequeue activity
- Fetch all behaviors from
/sys/behaviors - Match each behavior using
frame(activity, behavior["when"], require_match=True) - Execute function for each matching behavior
- If
activity["result"]includes new activities, submit each withcontext = activity["id"] - On any exception:
- Append an error to
activity["result"] - Convert activity to a Tombstone
- Store updated activity
- Append an error to
For more detailed documentation, see the comments in the source code and the SPEC.md file.
# Install test dependencies
pip install -e ".[test]"
# Run all tests
pytest
# Run with coverage
pytest --cov=activity_busMIT