Your API is broken. If you require the user to use python code then yes you do have to evaluate it. eval
can be made harder to exploit by specifying which locals/globals the code evaluated can use, but it's extremely hard to make the code safe... moreover once you start blacklisting built-in functions and such it becomes extremely hard to code and the API because hard to understand since it's not really clear what you can or cannot do.
The correct way to handle this is to provide that information as structured data, not as executable code!
There are many existing formats such as JSON, yaml, xml etc.
I will use JSON as an example and since it is very common these days and the stdlib has an implementation:
import json
c = '''
{
"filter": Click Here To Open Google",
"button": {
"label": "Google",
"url": "google.com"
}
}
'''
data = json.loads(c)
filter = data['filter']
if 'button' in data:
options = data['button']
g = Button.url(options['label'], options['url'])
elif 'checkbox' in data:
# as an example
options = data['checkbox']
g = Checkbox.url(options['label'], options['url'], options['status'])
await event.reply(filter, buttons=[g])
Obviously depending on how much power you want to give to the user the data will become more and more complex and so more and more complicated to handle. You have to think what the user might want to do, and how that information can be specified as data and how to handle it. This is no easy or simple task. Unfortunately we cannot really help you with this since you provided a single example while this requires a complete knowledge of the use cases that should be supported.
eval
might be useful for early prototypes or home mode scripts not meant for others or the internet.
Extra bonus of using data: you can now reimplement a part of your application in a different language easily. If you used python you'd have to implement a full python interpreter instead.