What a PyRIT migration involves
The migration starts from one fact: the original Azure/PyRIT repository was archived on 27 March 2026 and is now read-only, so it will receive no further changes. Development continues at microsoft/PyRIT, and the current release line includes v1.1.0, released on 4 September 2026. Any code that still points at the old repository, installs from it, or expects it to receive fixes needs to be moved to the new project and its published releases.
The work usually surfaces in four places. Forks that still track the old repository need a new upstream and a deliberate merge. CI pipelines and requirements files that pin old versions must be updated and their builds rerun. Internal wrappers that import old module paths will fail or behave differently once they are pointed at the 1.x line. Finally, custom targets, converters, scorers and attacks must be retested against the new release, because a passing import does not show that a multi-turn attack or a scorer still produces the same results.
For a small codebase with a few custom targets and scorers, a team with Python and test engineering skills can often do the move itself. The checklist is an inventory of references, a version pin, a full run of existing scenarios, and a comparison of results against earlier runs. Larger estates, with many custom attacks, shared red teaming workflows and stored results that others depend on, usually benefit from a partner who scopes the inventory and retests those components in writing before the old pins are removed.
Confirm before you start: list every repository, pipeline, requirements file and internal package that references PyRIT, and record the Python version each environment runs. PyRIT supports Python 3.10 up to but not including 3.15, and the documentation recommends Python 3.13. Agree in advance who signs off on retested results before the old code is retired.
What the migration includes
Each card is a separate work package. The exact deliverables are fixed in writing from the agreed scope before work starts.
Inventory and import mapping
List every fork, pinned version, script and internal tool that imports from the archived Azure/PyRIT repository. For each item, map old import paths and configuration keys to the microsoft/PyRIT 1.x layout, and record what changes and what is removed. Check scheduled scans and CI jobs too, since they often hide the most callers.
Python environment and settings
Build the target environment on a Python version the PyPI package supports, which is 3.10 up to but not including 3.15. The PyRIT documentation recommends 3.13. Move credentials in ~/.pyrit/.env and settings in ~/.pyrit/.pyrit_conf, and confirm which values each host reads so secrets stay in your approved secret store.
Custom targets, converters, scorers and attacks
Port your custom HTTP or WebSocket targets, converters, scorers and multi-turn attacks to the 1.x interfaces. Check how each component calls models, handles retries and returns results, since these behaviors can change between releases. Keep each port in version control so reviewers can compare old and new logic side by side.
Retesting custom attacks
Run every migrated attack against a fixed set of known test cases with expected outcomes, and compare the results with the pre-migration baseline. Record differences in scorer verdicts, response handling and error paths. Treat unexplained changes as failures until the team agrees on the cause, and rerun the set after any dependency change.
Memory continuity
Decide whether existing results move with the team. Confirm whether data in your current SQLite memory can be read by the 1.x memory layer or needs conversion, and whether Azure SQL is the right store for shared use. Test reads of historical conversations and scores before cutover, and confirm that access controls match your data handling policy.
Handover package
Deliver a changelog of every change from the archived repository, a test record showing which cases passed and why any failed, and a rollback note naming the prior pinned versions and the steps to restore them. Ask for the package to be reviewed by the team that will own PyRIT after handover.
What drives migration effort
This table lists the factors that change how much work a move from the archived Azure/PyRIT repository to microsoft/PyRIT and the 1.x line takes, why each one matters, and how to keep it manageable.
| Driver | Why it changes effort | How to keep it down |
|---|---|---|
| Forks and internal repositories | Each fork carries its own pinned dependencies, patches and CI configuration, so every copy has to be reconciled with microsoft/PyRIT separately. | Freeze the inventory early, list every fork and internal repository with its owner, and decide per repository whether it is merged, rebased or retired. |
| Custom targets | Targets for OpenAI, Azure, Anthropic, Google, Hugging Face, custom HTTP or WebSocket endpoints and Playwright-driven web apps each have their own configuration and authentication, and custom ones need code review against the new target interface. | Inventory each target, record which provider class or custom code it uses, and move only the custom endpoints into bespoke code while using built-in targets where they fit. |
| Custom converters, scorers and attacks | Each custom component depends on internal PyRIT APIs that may have changed between the archived repository and the 1.x line, so each one needs a compatibility check and a test. | Keep custom code thin, wrap business logic outside PyRIT classes, and remove custom components that duplicate built-in converters or scorers. |
| Multi-turn strategies such as Crescendo, TAP and Skeleton Key | Multi-turn attacks depend on conversation state, scoring thresholds and attacker model settings, so a change in orchestration or memory behavior can alter results without raising an error. | Document the exact strategy settings in use, and rerun each strategy against the same reference target before and after the move. |
| Memory backend: SQLite or Azure SQL | Teams using Azure SQL carry connection, firewall and schema concerns that SQLite installs do not, and any schema change between versions must be planned for both backends. | Confirm which backend each environment uses, test the migration path on a copy of the stored data, and keep backend settings in one documented configuration file. |
| Test environments and Python versions | Each environment, such as a laptop, CI runner or shared test host, may run a different Python version, and the PyPI package supports Python 3.10 up to but not including 3.15, while the documentation recommends 3.13. | Pin one Python version per environment, align them on the version the documentation recommends where possible, and rebuild each environment from the same lock file. |
| Test coverage of existing behavior | Where old behavior is covered only by manual runs or memory of past results, it is hard to tell whether a change in output is a regression or an expected improvement. | Write characterization tests for the attacks, scorers and targets that matter most before the move, and record which behaviors have no test. |
| Comparability of earlier results | If findings from earlier runs must be compared with new runs, scorer versions, prompt datasets and model versions all have to match, or differences will reflect the tooling rather than the target. | Write a fixed set of reference prompts before the move, store the scorer and model versions used for each baseline run, and rerun the set on both versions. |
Migration phases and outputs
The sequence moves PyRIT workloads from the archived Azure/PyRIT repository to microsoft/PyRIT on the 1.x line, with a recorded output at each phase.
Inventory forks, pins and custom components
Your team and DeployOpen list every fork of Azure/PyRIT, each pinned version, every import of PyRIT modules, and each custom target, converter, scorer or attack. Each item gets an owner and a migration status. The inventory is complete when no custom code or pin remains unlisted, and the written scope is set from it.
Run gap analysis against 1.1.0
Compare each inventory item with the PyRIT 1.1.0 documentation and release notes, published on 4 September 2026. The output is a list of changed interfaces, with the file and function affected and the fix required. The list is reviewed by the code owners before any code changes begin.
Build a reproducible Python environment
Define the Python version and the full dependency set in a lock file or container image. The PyPI package supports Python 3.10 up to but not including 3.15, and the documentation recommends 3.13, so confirm the version your organization will standardize on. The output is an environment definition that rebuilds identically on every test and production host.
Migrate code and configuration to microsoft/PyRIT
Create a branch or fork from microsoft/PyRIT and apply the interface fixes from the gap list. Update dependency pins, credential loading from ~/.pyrit/.env, settings from ~/.pyrit/.pyrit_conf and memory configuration. The output is a branch with updated pins and a change log that links each fix to an inventory item.
Retest custom attacks and scorers
Run every custom attack, converter and scorer on the archived and migrated code, using the same targets and datasets. Record prompts, responses, scores and errors side by side. The output is a test record that shows where behavior matches and where it differs, with each difference accepted or fixed by its owner before cutover.
Agree cutover and rollback plan
Set the order of switch-over, the acceptance criteria drawn from the test record, and the change freeze window in the written scope. Write the rollback procedure, including how to restore the archived environment and the memory database. The output is a runbook that names who approves cutover and who reverts it.
Hand over with documentation
Transfer the environment definition, branch, test record, runbook and list of known behavior differences to your team. Walk through routine operation, including scheduled scans, credential handling and memory storage. The output is a handover package that lets your staff run and update PyRIT without the migration team.
What teams keep in-house and what they outsource
This table shows each part of a PyRIT migration from the archived Azure/PyRIT repository, who usually owns it, and the skills each part requires, so you can match work to your own team or a partner.
| Work area | Usually owned by | Skills required |
|---|---|---|
| Inventory of forks, consumers and custom code | In-house | Knowledge of your own forks, internal consumers and which team relies on each custom target, converter or scorer |
| Dependency and environment work | Either | Python packaging, pinning and virtual environment management, and CI configuration for Python 3.10 to 3.14 builds |
| Code migration of custom targets, converters and scorers | Often outsourced for large estates | Python and API integration skills, plus familiarity with PyRIT's target, converter and scorer interfaces |
| Retesting of custom attacks | Either, with in-house sign-off | Red teaming domain knowledge and a test harness that replays attacks against the migrated code |
| Memory and result continuity | Either | Database and data handling skills for SQLite or Azure SQL memory, including schema checks and preservation of historical results |
| Documentation and handover | In-house owner required | Technical writing for your environment, plus a named maintainer who will track future PyRIT releases |
What goes wrong and how to prevent it
Most PyRIT migration problems come from old references that keep working without errors. Check each failure point before cutover and keep the checks in your release process.
Old imports and pins
Internal tools and requirements files can still import from or pin the archived Azure/PyRIT code path. They keep running without errors while missing development that continues only at microsoft/PyRIT. Search repositories, CI files and lockfiles for old references, then rebuild a pinned environment file that installs the 1.x line and run each internal tool against it.
Forks drifting from upstream
A fork of Azure/PyRIT that received local patches during the project can drift further from microsoft/PyRIT over time. Record each local patch, decide whether it moves upstream or is dropped, and freeze the fork at an agreed commit for cutover. Ask who owns rebasing after handover.
Custom scorers changing verdicts
A custom scorer that passed on the archived code can return different verdicts on the 1.x line, which breaks trend comparisons with earlier runs. Before cutover, run a reference prompt set through both versions, record every verdict difference, and fix or document each one. Apply a freeze window so no scorer changes land mid-comparison.
Credentials left in old locations
Older setups may keep API keys in shell profiles, scripts or configuration files outside PyRIT's own settings. PyRIT reads credentials from ~/.pyrit/.env and settings from ~/.pyrit/.pyrit_conf, so move each secret there, rotate any key that was copied elsewhere, and search old hosts and build agents for leftover copies before retiring them.
Unsupported Python in build agents
The PyPI package supports Python 3.10 up to but not including 3.15, and the PyRIT documentation recommends Python 3.13. Build agents pinned to an older interpreter, or to a version outside that range, fail at install or at runtime. Check each agent's interpreter, set the version in the pinned environment file, and test the install on every agent image before cutover.
Untested memory restore
PyRIT memory stores conversations and results in SQLite or Azure SQL. Teams often confirm that writes work but never restore a backup into a clean environment. Run a dry run that restores the memory backend, opens past results in PyRIT, and confirms that scores, targets and attack records still match before the archived store is retired.
How the work differs by starting point
A fork carries your own changes on top of the archived code, so the work is reconciling each patch with the 1.x line. Effort depends mostly on how many patches exist and how far they touch core modules.
- Patch inventory: list every local change, its purpose and whether upstream already covers it.
- Patch-by-patch review: re-apply each change to a 1.x base and record what no longer applies.
- Verification: rerun your custom attacks, converters and scorers against the new base and compare results.
- Ongoing divergence: decide whether to keep the fork, move patches into your own package or drop them.
Other projects import PyRIT as a library, so the migration is a version pin update plus fixes to any calls that changed. Changes are usually confined to call sites you own, but they can appear anywhere your code touches the framework.
- Find every pin: search repositories, lockfiles and container images for PyRIT imports and version constraints.
- Check release notes: review the 1.x changelog for renamed, moved or removed calls.
- Confirm Python support: the PyPI package supports Python 3.10 up to but not including 3.15, and the documentation recommends 3.13.
- Test before pinning: run existing test suites and a smoke attack against a non-production target before changing production builds.
Wrappers around pyrit_scan or the Python framework depend on command-line options, configuration files and object interfaces. Rework covers the wrapper itself and checks that each invocation still behaves as before.
- CLI checks: list every pyrit_scan option your wrapper passes and confirm each one against the 1.x documentation.
- Configuration: confirm that settings in ~/.pyrit/.pyrit_conf and credentials in ~/.pyrit/.env still load as expected.
- Custom classes: rework any target, converter or scorer classes that the wrapper imports.
- Output comparison: compare results, memory records and exit codes from a fixed set of test runs before and after the change.
Teams using CoPyRIT or a shared memory store have conversations, scores and reviewed findings that must move with the code. The main risks are data loss and access that was granted under the old setup.
- Identify the backend: confirm whether memory uses SQLite or Azure SQL, then plan the export, schema check and import.
- Back up first: take a full backup before any upgrade and keep it until migrated results are verified.
- Access review: list who can read and write shared results and reapply access to match current team roles.
- Result checks: confirm that historical findings open correctly and that scores still match their source conversations.
Restricted networks cannot pull packages from PyPI or GitHub during the move, so every dependency and the 1.x release must be mirrored first. Most of the work happens before cutover.
- Mirror dependencies: copy the PyRIT package and its full dependency tree into your internal index, pinned to the version you will run.
- Transfer sources: bring in the release source and documentation through your approved transfer process and record checksums.
- Check the runtime: confirm the Python version in the restricted environment falls within the supported range.
- Test the mirror: install from the mirror on an isolated host and run your tests, including any target connectivity they need, before moving production work.
What you need to provide
The migration can only be scoped and cut over safely if you give us a complete inventory of what depends on the archived Azure/PyRIT repository. Start with read access to every fork, internal repository and CI definition that references PyRIT, including pinned requirements files, pipeline steps that clone or install from Azure/PyRIT, and internal wrapper packages. Source control administrators or the platform engineering team usually own this access. Without it, pinned dependencies that were missed will surface after cutover, not before.
Next, provide a list of every custom target, converter, scorer and attack your team has written, with a named owner for each. Custom code is where migration effort concentrates, because the 1.x line is where any API changes will need to be reconciled. For each custom attack, supply sample inputs and the outcomes you expected, such as the scorer result or the category of response the attack should produce. This baseline is what lets us tell whether a changed result after migration reflects a regression or a deliberate change in behavior. The red teaming lead usually owns the expected outcomes, and the engineers who wrote each attack own the sample inputs.
Confirm the build environments and Python versions in use. The PyPI package supports Python 3.10 up to but not including 3.15, and the PyRIT documentation recommends Python 3.13, so you should state which interpreter each pipeline and workstation runs and whether any host is locked to an older version. You also need to decide the memory backend, SQLite or Azure SQL, and where results are stored. This decision affects data residency, access control and how the migrated conversation history is moved. The platform owner and the security team should agree on it together, since it determines who can read stored prompts and outputs.
Finally, name a technical owner who can make decisions about dependencies and environments during the migration, and a red teaming lead who can judge whether changed results are acceptable. Those two roles should not be the same person in practice, because the first is accountable for working software and the second for the quality of the testing. Agree a change window for cutover with operations and the teams that run tested systems, and ask them to confirm how rollback is handled. Confirm all of these owners and dates in writing before scoping begins.
Frequently asked questions
Can our team migrate without a partner, and what should we check first?
Yes, for small, well-tested codebases, an in-house team can usually handle the move if it inventories everything first. Check first: every fork and internal tool that imports PyRIT, the pinned version in each, and whether your tests cover custom targets, converters and scorers. Confirm the Python interpreter too. The PyPI package supports Python 3.10 up to but not including 3.15, and the documentation recommends 3.13. Larger setups with many custom attacks, shared memory or several environments often benefit from a second set of hands.
What drives the cost and effort of a PyRIT migration?
The main driver is the amount of custom code, not the size of the install. Custom HTTP or WebSocket targets, Playwright-driven web app targets, custom converters and scorers, multi-turn attack logic and the number of forks and environments all add work. Memory setup in SQLite or Azure SQL and dependency pinning also count. Recurring costs include model API calls used to retest attacks, which are separate from labor. In a quote, ask for effort by component, what is one-time versus recurring, and which assumptions the estimate relies on.
How long does a PyRIT migration take?
No duration is fixed in advance. The timeline is set in the written scope after an inventory of your forks, pinned dependencies, custom attacks and tooling, because the amount of code to move and retest drives the schedule. Engagements are fixed-scope, so the agreed scope sets the timeline and deliverables. Ask for the plan to show the inventory, the migration of each component, retesting against your own cases, client review points and handover, so you can see where time goes.
What do we need to prepare before a PyRIT migration starts?
Gather a readiness list before work begins: every fork, branch and internal tool that imports PyRIT, the pinned version in each, and copies of your custom targets, converters, scorers and attack code. Add the test cases you use to judge results, the settings and environment files in ~/.pyrit/ (with credentials kept out of shared documents), access to a test environment with model endpoints you are permitted to test, and one named owner for decisions. Confirm the approval and access process with your security team.
Does the archived Azure/PyRIT repository still receive fixes?
No. The Azure/PyRIT repository was archived on 27 March 2026 and is read-only, so it receives no new fixes. Development continues at microsoft/PyRIT, and PyRIT v1.1.0 was released on 4 September 2026. Point forks, pinned dependencies, package sources, CI configuration and internal documentation to microsoft/PyRIT. Vulnerabilities are reported privately through the Microsoft Security Response Center under the project's security policy.
How do we confirm breaking changes after moving to 1.1.0?
Compare your code with the 1.1.0 documentation and the release notes on the microsoft/PyRIT releases page, then test against your own cases. List every PyRIT API your code calls, including targets, converters, scorers, attacks and memory, and confirm that each signature and behavior still matches. Rerun your attack cases and compare the results with your previous baseline. Keep the test cases and expected outcomes in version control so the same check repeats on every upgrade.
How DeployOpen delivers this migration
DeployOpen moves your forks, pinned dependencies and internal PyRIT tooling from the archived Azure/PyRIT repository to microsoft/PyRIT and the 1.x release line, then retests your custom attacks against the new version. The work runs under a written scope inside infrastructure you control.
How we scope
- The written scope lists every fork, pinned dependency and internal script that references the archived Azure/PyRIT repository.
- Custom targets, converters, scorers and attack strategies are inventoried so each one has a named owner and a retest plan.
- Engagements are fixed-scope, with deliverables and timelines agreed in writing before migration work begins.
- Ask the scope to state which Python versions and PyRIT release you will move to, and who confirms them.
How we build
- Forks and pinned dependencies are repointed to microsoft/PyRIT, and import paths and configuration changes are recorded in version control.
- Custom attacks, targets and scorers are rerun against the 1.x line and compared with results from the original setup.
- Credential and settings files, including the ~/.pyrit/.env and ~/.pyrit/.pyrit_conf locations, are moved without exposing secrets in repositories.
- Test runs are performed in your environment against targets you have authorized, with memory storage configured for your chosen backend.
How we hand over
- Handover includes a migration record listing each change, the reason for it and the test evidence that supports it.
- Your team receives updated internal tooling documentation covering how to install, pin and run PyRIT in your environment.
- Retested custom attacks come with a short runbook that states which results changed after migration and why.
- Confirm with DeployOpen which artifacts are delivered to your repositories and which remain with your team.
How we support
- Ongoing support for PyRIT upgrades and custom component validation is available as a retainer after handover.
- Retainers can cover checking new PyRIT releases, such as the v1.1.0 release, against your custom targets, converters and scorers.
- Support requests are handled inside your infrastructure and within the agreed retainer terms.
- Ask for the support scope, response expectations and upgrade cadence in writing before the retainer starts.

