Human-in-the-loop for security agents
Containment is a decision, not a trigger.
The on-duty analyst authorises the containment from their phone, and the authorisation is recorded as part of the incident.
How does a SOC AI agent get an analyst to authorise a containment action?
Pushary reaches the on-duty analyst on their phone and blocks the agent until they authorise. Put decisions.ask() in front of the isolation, the account disable, or the block, and the agent holds on a durable wait instead of firing on a confidence score. Timeouts resolve denied, and the authorisation is written to a ledger you can attach to the incident record.
Where it stops
The calls that should not be automatic
- isolateHost(hostId)
- Pulling a machine off the network stops an intrusion and stops the person using it. On the wrong host during business hours that is its own incident.
- disableAccount(userId)
- Disabling the wrong account locks out someone who was doing their job, and a false positive here is felt immediately by a real person.
- blockIndicator(type, value)
- Blocking an indicator that turns out to be shared infrastructure takes down services that had nothing to do with the alert.
- revokeSessions(userId)
- Mass session revocation is a reasonable response to credential theft and an unreasonable one to a noisy detection, and telling those apart is the analyst's job.
The integration
Two calls inside the step you already have
Wrap the action, not the whole agent. Everything the agent does that is safe keeps running without asking anyone.
from pushary import Pushary
px = Pushary(api_key=os.environ["PUSHARY_API_KEY"])
def contain(alert, action):
# Enrichment and evidence collection never wait for anyone.
context = enrich(alert)
if action.reversible and context.confidence > 0.95:
return apply(action)
decision = px.decisions.ask(
external_id=alert.duty_analyst_id,
type="confirm",
question=(
f"{action.summary} on {action.target}? "
f"Confidence {context.confidence:.0%}. Impact: {action.user_impact}."
),
)
if not decision.approved:
return annotate(alert, "containment not authorised")
return apply(action)Who answers
The approver is usually not an engineer
The approver is the analyst on duty, and out of hours that is one person covering a lot of surface. The usual pattern is a bot posting the proposed containment into a channel with a button, which works during the day and degrades badly at night, because at 03:00 the question is whether anybody is looking at that channel at all. The consequence of nobody looking is not a stalled ticket, it is an intrusion continuing while a correct decision waits. Pushary reaches the analyst by the id your duty rota already knows, on a channel built to wake someone, and returns their answer to the agent as a value it can branch on.
If we wait for a human, does the attacker not just get more time?
Sometimes, which is why the choice is per action rather than per incident. Enrichment, evidence collection, and anything cleanly reversible should run immediately and be reviewed after, and most of what a SOC agent does falls in that group. The actions worth gating are the ones whose cost when wrong is comparable to the cost of the intrusion: isolating a production host, disabling an executive's account, blocking shared infrastructure. For those, firing on a confidence score is not faster, it just moves the outage. What makes gating viable is the delivery being fast enough that the wait is measured in a minute rather than until somebody notices a channel, and the timeout being an explicit denial you can see in the record.
Worth reading: NIST SP 800-61 on computer security incident handling.
Embed it in your product. Your users never see a Pushary login or bill.
FAQ
Questions, answered
Put a person on the step that needs one.
Connect a user with one tap, ask a human with one call, and act on a fail-closed decision. Every decision is saved to a durable ledger you can audit.