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.

pip install pusharytwo calls
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.

$99/ month, Partner plan

Embed it in your product. Your users never see a Pushary login or bill.

FAQ

Questions, answered

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.
Can we auto-approve high confidence detections and gate the rest?
That is the recommended shape and it lives in your code. Branch on reversibility and confidence, apply the action directly when both are comfortable, and call decisions.ask() otherwise. Keeping the gated set small is what stops analysts approving reflexively.
Does this replace our on-call paging tool?
No. Paging tells a person something is happening. This asks them a specific question and returns their answer to the agent that is waiting, which a paging tool does not do. Teams generally keep both, because the alert and the authorisation are different jobs.
What does the incident record look like afterwards?
Each authorisation is a ledger row with the question as the analyst saw it, including the confidence and impact you put in it, their answer, their identity, and the timestamp. It exports, and resolved decisions post a signed webhook if you want them written straight into your case management.
What if the analyst is mid-incident and misses it?
The decision fails closed and the containment does not happen, which is the safe default for an action you decided was risky enough to gate. Your agent can then escalate to a secondary analyst using a different externalId, and the unanswered request stays visible in the ledger.

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.