I chained three StreamForce agents into a weekly pipeline that takes an attack path all the way to a pull request. The first agent finds what makes the path exploitable and checks what is actually in use. The second runs each proposed fix through Stream's change simulation, and the third writes the fix in Terraform and opens a draft pull request.
In the example below, one pull request removed admin privileges and internet SSH exposure from an internet-facing EC2 instance, and the one legitimate SSH user on the same security group kept working. Nothing in the cloud changes until someone reviews the pull request and merges it.
Fixing an attack path sounds simple until you look at what else depends on the same configuration. A security group usually protects more than one server, and a role often serves more than one workload. The rule that exposes one machine can be the exact rule another machine needs every day.
So before anyone changes anything, someone has to work out what each resource really uses, who connects to it, and what happens if the rule gets tighter. Done by hand that is slow work, and a lot of paths just stay open.
StreamForce agents can do that work on a schedule. My pipeline has three of them, chained, so each one starts when the previous one finishes and passes its results along.
Discovery goes over every attack path in scope, finds the configuration behind it, and uses VPC flow logs and CloudTrail activity to see what is actually used. It then proposes the smallest set of least-privilege changes that closes the path without cutting off legitimate access.
Simulation runs each proposed change through Stream's change simulation, which predicts which attack paths would close and which new ones would open, before anything is deployed. Every fix gets a verdict before it goes any further.
The Pull Request agent turns the approved fixes into infrastructure as code, Terraform in this case, and opens a draft pull request.
None of the agents know anything about a specific scenario. Their instructions describe how to remediate an attack path in general, so the same three agents can work on any path in scope.
This is the chain in StreamForce. Discovery runs on a schedule, and the other two start as soon as the step before them finishes.

To show how it works, I deployed a small AWS environment with Terraform from a GitHub repo. It has three EC2 instances:
Stream flags both servers. yoni-demo is the dangerous one. Anyone on the internet can reach it over SSH, and its role has full admin rights, so a single compromised server means full account takeover.
That mix of internet exposure and admin privileges is a classic toxic combination. yoni-demo-web is exposed through the same rule, and its attack path already shows the admin host's legitimate traffic as the dotted line on the right.

The flow logs tell the rest of the story. Over about three weeks, 1,757 different internet IPs probed port 22 on the web server and none of them completed a TCP handshake. The admin host completed a full session every 5 minutes.
The obvious fixes both cause problems. If you delete the SSH rule, the admin host can't reach the web server anymore. If you narrow the rule to the admin host's IP, yoni-demo is still open to SSH, now from a machine that never talks to it.
What actually works is moving yoni-demo to its own security group with no inbound rules, narrowing the shared group to the admin host's IP with a /32 rule, and replacing AdministratorAccess with a least-privilege policy that covers only what the log job uses. I didn't tell the agents any of that.
Discovery only reads. For every attack path it finds the configuration that makes the path exploitable, measures actual usage over the last 90 days (or whatever history exists), and checks which other resources share that configuration.
You control how it decides through plain-language rules in its instructions. Three of them do most of the work in this example. The first one tells legitimate users apart from scanners in the flow logs:
Real users vs. scanners: a real user completes its connections (tcp_flags include
FIN or RST, not only SYN) and does so regularly across the window, for example every
few minutes or every day, even if it is automated. Sources whose connections never
complete (tcp_flags 2, SYN only) are scanners, however often they repeat.
That is how it picked the admin host out of all the noise on port 22. The second rule protects shared configuration:
Never change a configuration that another resource really uses. Give the path's
resource its own new configuration instead, for example its own security group or role.
And the third keeps the new IAM policy tight:
Only actions with evidence: every action in a proposed policy must come from a logged
event or from what the resource's own configuration shows it does. Never add actions
because they are commonly needed.
For each fix, Discovery writes a small JSON block that the next agents read. A shortened version of the network fix, with example IDs, looks like this:
{"v": 2,
"issue": "Shared security group allows SSH from 0.0.0.0/0 to an instance with an admin role",
"evidence": {"granted": "TCP 22 from 0.0.0.0/0",
"used": "no inbound SSH to yoni-demo; scanners only", "days": 23},
"changes": [
{"action": "created", "resource_type": "security_group",
"resource_id": "sg-0new0000000000001", "name": "yoni-demo-dedicated",
"desired": {"IpPermissions": []}},
{"action": "modified", "resource_type": "instance",
"resource_id": "i-0123456789abcdef0", "name": "yoni-demo",
"desired": {"SecurityGroups": ["sg-0new0000000000001"]}}
]}
This is what Discovery reported for the demo environment. It found 672 SSH connection attempts on yoni-demo in 23 days, all from scanners, and only 9 distinct IAM actions used by its role.


Simulation is the step that makes me comfortable opening a pull request at all. It runs every proposed change through Stream's change simulation and gets back the attack paths the change would close, the ones it would open, and any new policy violations. Nothing is applied to the account.
It builds each change from the resource's current configuration in Stream's inventory and only touches the fields the fix calls for. Some links are stored on more than one record. An instance's security groups, for example, also live on its network interfaces (ENIs), so it changes all of them.
Each fix then gets a verdict, checked in this order:
not_simulated: the result is still a no-op or has errors after the retry, or the fix
removes or narrows access but the result closed no path.
unsafe: the result adds a high or critical violation, or opens new paths
although the fix creates nothing new.
review: the fix creates a new configuration to keep real users working, the
result closed paths, and it also opened some through the new configuration.
safe: at least one path closed, no path opened, and no new high or critical
violation.
Unsafe fixes never make it into the pull request. Fixes marked review do, with a note that explains what opened and why someone should look at it.




The last agent writes the code. It uses a custom plugin that runs in your own cloud and holds a fine-grained GitHub token, so the token never leaves your environment.
The plugin gives the agent three tools. getRepoTree lists the files in a repository, getFileContent reads a file, and createPullRequest commits exact find and replace edits to a new branch and opens a draft pull request. If any edit doesn't match the file exactly, nothing gets written, and the tool has no way to push to the default branch or merge anything.
The agent only writes the changes Simulation tested. In this example that meant one commit to one file: a new security group for yoni-demo, the shared group's SSH rule narrowed to the admin host's IP, and AdministratorAccess swapped for a least-privilege inline policy. Everything else in the file stayed as it was.
Each fix gets its own section in the pull request, with the evidence and the simulation result, so the reviewer can understand it without opening Stream.

The agents never change anything in the cloud. They read your environment and your code, and the only thing they create is a draft pull request that a person has to merge.
Everything they keep is backed by evidence from VPC flow logs, CloudTrail activity or the resource's own configuration. If some data is missing, Discovery says so and lowers its confidence instead of treating silence as no activity.
Shared configuration gets checked before it's touched, so every resource that uses a security group or a role keeps working for its legitimate users. Every fix is simulated before it's proposed, and anything unsafe stays out of the pull request.
When the Pull Request agent looks for a resource in the code, it matches on the exact name from Stream's inventory. If it can't find exactly one match, it says so instead of guessing.
You can scope the pipeline to one account or a set of tags, or run it across everything. It can run on a schedule or whenever you start it, and you can connect your own repositories and tools with custom plugins.
If I were setting it up for the first time, I would start with one account, review the pull requests it opens for a couple of weeks, and widen the scope once I trusted the results.
Stream is the AI-native platform built to fight AI-enabled attacks. It autonomously prevents, detects, hunts, and remediates exposures and threats across production at machine speed - driving risk toward zero. It replaces the fragmented stack of scanners, runtime agents, exposure tools and playbooks with one live model of production.Defending Production needs a new approach: Stream is the only Autonomous Production Defense Platform that works across your entire production estate. It runs on a patented CloudTwin®, a high-fidelity security data harmonization layer that models Cloud, SaaS, identity, runtime, AI, network, perimeter, on-prem, security controls, and the behavior running on top of them into one live model of production: real-time, fully correlated, continuously updating. Not a snapshot. And it does not stop at boundaries - the boundaries that fragment every other tool are the same boundaries an attacker moves across. Inside CloudTwin they are one system.