Rules for coding agents¶
These rules are for an agent writing an application on python-cqrs 5.2 or newer. They are also the first section of llms.txt.
Requests and handlers¶
- Commands and queries are both
cqrs.Request. There is noQueryclass and noCommandBus. - There is no
register_handlerdecorator. Register withmapper.bind(RequestType, Handler). - One handler per request type. A second
bindfor the same request raisesKeyError. - An event may have many handlers.
EventMap.bindappends.
Types to copy¶
A request that returns data:
class ReadMeetingQueryResult(cqrs.Response):
users: list[str]
class ReadMeetingQuery(cqrs.Request[ReadMeetingQueryResult]):
meeting_id: str
class ReadMeetingQueryHandler(cqrs.RequestHandler[ReadMeetingQuery]):
async def handle(self, request: ReadMeetingQuery):
return ReadMeetingQueryResult(users=["1", "2"])
Do not add -> ReadMeetingQueryResult on handle. await mediator.send(query) is ReadMeetingQueryResult.
A command with an empty body:
class JoinMeetingCommand(cqrs.Request[None]):
user_id: str
meeting_id: str
class JoinMeetingCommandHandler(cqrs.RequestHandler[JoinMeetingCommand]):
async def handle(self, request: JoinMeetingCommand):
print(request.user_id, request.meeting_id)
handle returns None. Do not annotate it.
Legacy (still supported): RequestHandler[Request, Result] with a return annotation on handle still works and is not the form to copy. Do not rewrite existing handlers. send on an unparameterized Request is Any.
The same parameter types a stream element (StreamingRequestHandler[Command] with Request[ItemResult]) and PydanticRequest[Result] when the pydantic extra is installed.
What the library does not check¶
- A read handler should not write state and should not fill
events. A command handler may. The library does not enforce that. - Publish to a broker through the transactional outbox. Do not write the business row and then publish to the broker in the same handler.
- Use a saga for a step that has compensation across services, not for a single
UPDATE.
Extras¶
Install extras explicitly: pydantic, sqlalchemy, sqlmodel, kafka, and the others listed in the library pyproject.toml.
Examples¶
Further reading: Request handlers, streaming, chain of responsibility.