I am trying to write a custom AI API for a game which uses the Unreal engine 4. While I can read the process memory using Python just fine, I have confronted a bigger issue - reading the process memory only when relevant and sending in inputs only when possible - thus only once a frame is rendered. If I want to send inputs, they need to be sent on frames specifically (the game being a fighting game).
Therefore, I need to update my own AI API with the same framerate as the game itself. My first idea was to look into the process memory and find out if there's any value that's updated each frame - while there're values updated all the time, they seem to be updated in memory after 8 frames occur. Unfortunately, 8 frames don't allow the AI to perform the inputs properly as the update loop would not update fast enough.
I will be looking through the memory more but I was wondering if it's possible to attach a program to the running process to look at the window itself - and in case it has been updated (something new has been rendered), update the gamestate in the AI itself. Is there a way this can be achieved?
We are talking about a game built on Unreal Engine, and you cannot find an address being changed every frame.
This makes me concerned about where/how you are trying to find the addresses being changed each frame. Perhaps try a memory scanning tool such as CheatEngine just in case.
There should be a few addresses changing each frame. One that comes to mind would be:

One of the addresses referenced when using this function: UGameplayStatics::GetRealTimeSeconds(GetWorld());

If you really cannot find a variable changing each frame, then I offer you a solution to hook into a function called in the process every frame by doing the following:
This is not a complete solution by any means as this covers a subjectively complex topic that you will likely need to learn about from other sources.
[NOTE]
If this game uses an anti-cheat, you may be banned for this behaviour, I would suggest doing your research before attempting this. I take no responsibility for any issues or loss you may incur from the use of the following advice. 
Backup Option:

Using CheatEngine, open the target process.
Look for a function that is being called every frame (like so):


Find a variable you suspect is READ every frame (does not have to be changed)
Add it to your address list
Right-click the entry from the address list and select: Find out what accesses this address
Accept the prompt to attach a debugger to the process
Watch the count, is it going up extremely fast? Great! this is likely being read every frame
Stop the tool and click on the Instruction entry in the list that has the high count
Click the Show Disassembler button
You are now looking at the interpreted opcodes for the function that is accessing your address every frame
Simply right click the highlighted row and click Select current function to find the start of the function
I would personally toggle a breakpoint on this line (F5) with the game visible on the side to ensure it is being triggered each frame (continuing after each break with F9).

You now have the Base Address + Function Address in the Address column of the highlighted row.
Here comes the hard part that will require further explanation and will be a learning exercise that you will need to undertake.

Read up on patching a function by injecting code into the process or by modifying the process before you run it.
The injected code can communicate with your process via a Memory Mapped File or a Named Pipe, setting a flag every frame.
You will need to do this while retaining the original opcodes to ensure the program works as normal by either:


restoring after executing
OR
jumping to a code cave and executing original opcodes before jumping back
OR
Redirecting the function altogether (not suitable for your current use but worth reading about)
Hook a program to a running game, update each frame