You can accomplish a lot like this without parsing at the AST level as a lot of api calls are something like
async def make_call(arguments):
url = "..."
body = process_arguments(arguments)
response = await post(body)
return process_response(response)
so you can ultimately write
that_call = [url, process_arguments, process_response]
and then generate a bunch of sync and async closures that capture that_call and then call the right things. In the typical API that you might want to compose sync/async I find at least 90% can be generated that way but working at the AST level you can get the last bit.