My understanding of AMQP is that messages only have the following components:
Queues
The point of having the queue declared in there, is for celery to create those queues and set up the configuration with RabbitMQ.
For a lower level AMQP client, you need to first declare the queue, then the exchange, and then finally bind the exchange to the queue. Later when posting messages, you just post to the exchange.
It seems like celery use this structure to do it automatically.