A way to use dynamic members using username.
In this article we will see a way to assign members (also called agents)* the Asterisk queues, a username, to make its use and monitoring easier.
To better visualize Asterisk settings, I installed FOP2 which shows us a panel of queue calls, and bedding to show an example of statistics that can be collected.
An Asterisk, the use of dynamic members is usually done by means of numbers, generally representing a SIP extension. This makes it uncomfortable for the user. further, using usernames can better track statistics.
When we don't use username, the appearance of a call queue in the FOP2 panel might look similar to the following, only the extension numbers would be seen:

*Note: The expression “Agents” used in old Asterisk configurations, it is considered obsolete, because a file called agents.cfg was used, which is no longer necessary. Nowadays, it is possible to use the expression “Members” to prevent confusions.
To achieve our purpose we are going to use an attached text file, in my case I have called it users.txt, we save it in the Asterisk directory or wherever we want, then we will indicate your route.
You just have to make a configuration in the file /etc/asterisk/extensions.conf (keep in mind that we already have the queues correctly configured in /etc/asterisk/queues.cfg, with dynamic members it is not necessary to indicate these in that file)
The example configuration is this:
exten => _*[a-z].,1,NoOp(-- Petición de login de miembros --)
same => n,Set(VAR=${SHELL(grep ${EXTEN:1} /etc/asterisk/archivos/usuarios.txt -w)}) ; en un archivo guardamos los nombres válidos.
same => n,GotoIf($["${VAR}" = ""]?cuelga) ; si en el archivo no aparece el nombre tecleado por el operario, lo expulsa.
same => n,AddQueueMember(clientes,Local/${EXTEN:1}@atencion_clientes)
same => n,Set(DB(atencion_clientes/${EXTEN:1})=${CALLERID(num)}) ; almacenamos esa correlación en la base de datos interna de Asterisk.
same => n,Playback(agent-loginok)
same => n(cuelga),Hangup()
; para desregistrarse usamos el carácter 0 en vez de * con el mismo código.
exten => _0[a-z].,1,NoOp(-- Petición de deslogueo de miembros--)
same => n,RemoveQueueMember(clientes,Local/${EXTEN:1}@atencion_clientes)
same => n,Set(borrar=${DB_DELETE(atencion_clientes/${EXTEN:1})}) ; aquí se elimina la correlación, usamos una variable (borrar en este caso)
same => n,Playback(agent-loggedoff)
same => n,Playback(goodbye)
same => n,Hangup()
[atencion_clientes] ; este es el contexto que determina la llamada al miembro desde la cola, si está ocupado no hace nada, manda un mensaje por consola.
exten => _[a-z].,1,NoOp(-Llamada al miembro -)
same => n,Set(MIEMBRO=${DB(atencion_clientes/${EXTEN})})
same => n,GotoIf($[${SIPPEER(${MIEMBRO},curcalls)} = 1]?ocupado)
same => n,Dial(SIP/${MIEMBRO})
same => n(ocupado),NoOp(Miembro ocupado, llamada en cola
With this configuration, the user only has to type from the telephone terminal, an asterisk followed by your username to be registered, and you can already receive calls from that queue.
Something like that would remain:

In this way you can easily identify when you are on call:

By last, with the Asternic tool we can check how statistics can be obtained by user:

In addition to how I have presented it to you, could be done in other ways, for example with a database for user names, I put it with a text file for simplicity.
Be encouraged to share your own solutions or possible improvements that have occurred to you.