The g flag to Dial says (it might be slightly different depending on the version of Asterisk you are using):
g: Proceed with dialplan execution at the next priority in the current
extension if the destination channel hangs up.
The problem you are facing is that the Dial isn't being executed from dialplan, it's being executed by your AGI, so when Dial exits, that's the end of the story.
In order to make this work, I would do something like this...
First, open up extensions.conf and add something along these lines at the end (this is untested):
[failover]
exten => doit,1,Dial(SIP/${TARGET}@${IP1},30,g)
exten => doit,n,Dial(SIP/${TARGET}@${IP2},30,g)
Then, in your AGI:
// These set the necessary variables
$agi->set_variable('TARGET', $target);
$agi->set_variable('IP1', $ip);
$agi->set_variable('IP2', $ip2);
// And tell Asterisk where to go after the AGI exits
$agi->set_context('failover');
$agi->set_extension('doit');
$agi->set_priority(1);
exit(0);
Then fire up the Asterisk CLI and reload the dialplan:
user@host:~$ asterisk -r
*CLI> dialplan reload
Now when the AGI exits, it should drop to the failover context and do the Dial for you, falling through to the second Dial if the first fails for whatever reason.
If you need to do more processing after both Dial attempts, you will either have to do it in dialplan or you have to fire up another AGI after the fact.