opts.user_agent is now optional