How to know agi channel still is up from within an h exten in dialplan?

hello dear friends,
all of my incoming calls go to an agi file, and in file i use " $agi->exec(“DIAL LOCAL/”.$queue."@from-internal,g"); " for connecting to queue and then come back to agi. after this line in file i call an external api URL to log the call events in another server for some reasons:
http://10.1.10.59:11257/api/ca/v1/common/callevents’”
when agent hangup the call first , call come back to agi file and then api URL willbe called, (no problem)
when caller hangup the call first, call wont come back to agi so in h exten of main context , i call api URL with no problem
BUT
when agent and caller hangup the call simultaneous , api URL willbe called 2 times
one time form agi and another time form h exten of dialplan and it makes an error in my call event server

in my logs call wont come back to agi and h exten executed , but in fact agi is executing too , maybe in background.

please help me,
tnx million for ur kind help

Use hangup handlers instead of h extension

https://wiki.asterisk.org/wiki/display/AST/Hangup+Handlers
https://wiki.asterisk.org/wiki/display/AST/Hangup+Handlers+Specification

tnx for your relpy, but my problem is not h exten
my problem is agi channel that continues its work
why when both side hangup together agi execute my api too?!!!
how to identify which side hangup first in h exten???

You haven’t shown the precise configuration or console output so we can see what is actually happening. Asterisk does what it is told though, so it is likely your configuration itself is resulting in it happening.

tnx for your reply
acctually in console , it shows that call goto to h exten.
there is no log in console that agi is executing, :scream:
asterisk is executing agi (in backgrond) and then execute h exten
in asterisk console log i can see that just h exten is executes
but in reality first agi continue its work then call go to h exten in dialplan

[context]
exten => _49763xxx,1,agi(inbound-logger.php,${EXTEN})
exten => _49763xxx,n,verbose(${AGISTATUS})
exten => _49763xxx,n,verbose(${channelstatus})
exten => h,1,verbose($[${ack${app}${i}}])
exten => h,n,verbose(${AGISTATUS})
exten => h,n,Verbose(hangup cause : ${HANGUPCAUSE} for callid: ${callid})
exten => h,n,gotoif($[${AGISTATUS} != SUCCESS]?ack)
exten => h,n,hangup()
exten => h,n(ack),gotoif($["$[${ack${app}${i}}]"=“done”]?hang)
exten => h,n(ack),agi(ack-logger.php,${ivrkey},${calllogid},${callid},${uniqi},${actionid},${meta},${app},${i})

and this is mentioned part of my agi file : inbound-logger.php

$agi->exec(“DIAL LOCAL/”.$queue."@from-internal,g");
/////////////*END action-ack api call start az inja

            $data = array(
            'AckTimeType' => 9101,
            'Ek' => $ivrkey,
            'CallLogId' => $calllogid,
            'CallId' => $callid,
            'UniqueId' => $uniq,
            'ActionId' => $actionid,
            'Meta' => $meta
            );

            //LOG
            $log_msg = $uniq.'--'.$cid.'--'.$did.'--'.$callid.' now its time to CALL END ACK in inbound.conf';
            $log = logger($log_msg);

            $data_string = json_encode($data);
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url_ack);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'access-token: '.$token)
            );

            $resp = curl_exec($ch);

            $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

            curl_close($ch);
            $agi->verbose("*****".$callid."*******ack sent to DB successfully and Status : ".$status."");

and ack-logger.php

$data = array(
‘AckTimeType’ => 9101,
‘Ek’ => $ivrkey,
‘CallLogId’ => $calllogid,
‘CallId’ => $callid,
‘UniqueId’ => $uniq,
‘Meta’ => $meta,
‘ActionId’ => $actionid
);

            $data_string = json_encode($data);

            //LOG
            $log_msg = $uniq.'--'.$callid.'---The Parameters that will pass to ACK api : '.$data_string;
            $log = logger($log_msg);

            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url_ack);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'access-token: '.$token)
            );

            $resp = curl_exec($ch);

            //LOG
            $log_msg = $uniq.'--'.$callid.'---Executing Ack api';
            $log = logger($log_msg);
	$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

            curl_close($ch);
            $agi->verbose("*****".$callid."*******ack sent to DB successfully and Status : ".$status."");
            $agi->verbose("ACK Api STATUSSSS is".$status."");

tnx million for your follow up