Package com.tnsai.security.approval
Class InterruptService
java.lang.Object
com.tnsai.security.approval.InterruptService
Service for AG-UI interrupt pattern - blocking agent execution for human approval.
This service implements the AG-UI interrupt-aware run lifecycle, allowing agents to pause execution and wait for human input before proceeding.
AG-UI Interrupt Flow
1. Agent calls requestInterrupt() before critical action
2. Service creates interrupt, agent thread BLOCKS
3. AG-UI emits RUN_FINISHED { outcome: "interrupt", interrupt: {...} }
4. Frontend shows approval dialog
5. User approves/rejects
6. Frontend POSTs to /v1/runs/{runId}/resume
7. Service completes the future, agent thread UNBLOCKS
8. Agent continues or aborts based on result
Usage Example
InterruptService interruptService = new InterruptService();
// In agent action execution:
InterruptResult result = interruptService.requestInterrupt(
InterruptReason.HUMAN_APPROVAL,
Map.of("action", "delete_user", "userId", "123"),
Duration.ofMinutes(5)
);
if (result.isApproved()) {
// Proceed with action
deleteUser("123");
} else {
// Action rejected or timed out
throw new ActionRejectedException(result.getRejectionReason());
}
// From AG-UI endpoint (when user approves):
interruptService.resume(interruptId, true, Map.of("approver", "admin"));
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordInterrupt request details for listeners. -
Constructor Summary
ConstructorsConstructorDescriptionCreates an InterruptService with default 5 minute timeout.Creates an InterruptService with a listener for interrupt events.InterruptService(Consumer<InterruptService.InterruptRequest> listener, Duration defaultTimeout) Creates an InterruptService with custom timeout. -
Method Summary
Modifier and TypeMethodDescriptionbooleanCancels an interrupt.intGets count of pending interrupts.getPendingInterrupt(String interruptId) Gets details of a pending interrupt.booleanChecks if an interrupt is pending.requestInterrupt(InterruptReason reason, Map<String, Object> payload) Requests an interrupt and blocks until resolved or timed out.requestInterrupt(InterruptReason reason, Map<String, Object> payload, Duration timeout) Requests an interrupt with custom timeout.requestInterruptAsync(InterruptReason reason, Map<String, Object> payload, Duration timeout) Requests an interrupt without blocking (async).booleanResumes an interrupt with approval.
-
Constructor Details
-
InterruptService
public InterruptService()Creates an InterruptService with default 5 minute timeout. -
InterruptService
Creates an InterruptService with a listener for interrupt events.- Parameters:
listener- called when interrupt is requested (for AG-UI event emission)
-
InterruptService
public InterruptService(Consumer<InterruptService.InterruptRequest> listener, Duration defaultTimeout) Creates an InterruptService with custom timeout.- Parameters:
listener- called when interrupt is requesteddefaultTimeout- default timeout for interrupts
-
-
Method Details
-
requestInterrupt
Requests an interrupt and blocks until resolved or timed out.This method will:
- Create an interrupt request
- Notify any listeners (for AG-UI event emission)
- Block the calling thread until approval/rejection/timeout
- Return the result
- Parameters:
reason- the reason for the interruptpayload- additional data to show in approval UI- Returns:
- the interrupt result
-
requestInterrupt
public InterruptResult requestInterrupt(InterruptReason reason, Map<String, Object> payload, Duration timeout) Requests an interrupt with custom timeout.- Parameters:
reason- the reason for the interruptpayload- additional data to show in approval UItimeout- how long to wait before timing out- Returns:
- the interrupt result
-
requestInterruptAsync
public CompletableFuture<InterruptResult> requestInterruptAsync(InterruptReason reason, Map<String, Object> payload, Duration timeout) Requests an interrupt without blocking (async).- Parameters:
reason- the reason for the interruptpayload- additional data to show in approval UItimeout- how long to wait before timing out- Returns:
- future that completes with the result
-
resume
Resumes an interrupt with approval.- Parameters:
interruptId- the interrupt IDapproved- whether the action is approvedpayload- optional response payload from user- Returns:
- true if the interrupt was found and resumed
-
cancel
Cancels an interrupt.- Parameters:
interruptId- the interrupt ID- Returns:
- true if found and cancelled
-
getPendingInterrupt
Gets details of a pending interrupt.- Parameters:
interruptId- the interrupt ID- Returns:
- interrupt details or empty
-
getPendingCount
public int getPendingCount()Gets count of pending interrupts.- Returns:
- number of pending interrupts
-
isPending
Checks if an interrupt is pending.- Parameters:
interruptId- the interrupt ID- Returns:
- true if pending
-