All jobs

Upgrade Python Dependencies in a Streamlit App

Yes. Each week an agent upgrades a Streamlit app's requirements with pip, runs AppTest and ruff after each group, and opens one pull request.

Run this on RushIn a Project that has your repository.

What the agent does

The agent starts with the requirement files, because a Streamlit app rarely has a lockfile and the pins tell it which packages are free to move. In streamlit/llm-examples, requirements.txt has range pins on streamlit>=1.28, openai>=1.2, anthropic>=0.3.0 and trubrics>=1.4.3, bare names for duckduckgo-search and streamlit-feedback, and two exact pins that belong together: langchain==0.0.350 and langchain-community==0.0.3. requirements-dev.txt pins black==23.3.0, mypy==1.4.1 and pre-commit==3.3.3 exactly, with watchdog and pytest unpinned. There is no pyproject.toml and no lockfile, so the installed set is whatever pip resolves on the day.

Then it reads what the checks are. app_test.py holds two tests on streamlit.testing.v1.AppTest: one runs Chatbot.py, patches openai.resources.chat.Completions.create and checks the assistant message that comes back; the other runs pages/3_Langchain_Quickstart.py and patches langchain.llms.OpenAI.__call__. .github/workflows/app-testing.yml runs on Python 3.11 with streamlit/streamlit-app-action, pointed at Chatbot.py, with ruff: true and pytest writing a JUnit report. So the gate for every bump is pytest -v, ruff check . and each page starting under AppTest.from_file(...).run() with no exception.

The two exact pins decide the shape of the run. pages/2_Chat_with_search.py imports initialize_agent, StreamlitCallbackHandler, ChatOpenAI and DuckDuckGoSearchRun from the top-level langchain package, and pages/3_Langchain_Quickstart.py and pages/4_Langchain_PromptTemplate.py import OpenAI from langchain.llms. Later LangChain releases moved those classes into langchain_openai and langchain_community, which also changes the patch target in app_test.py. A LangChain major is therefore a code port across three pages and the test file, not a version bump; the agent keeps the pair pinned by default, tries the port in a separate commit, and keeps it only if the suite passes. pages/1_File_Q&A.py uses the Anthropic SDK's text-completions call with anthropic.HUMAN_PROMPT and the model name claude-v1; a newer SDK still installs, but the agent notes in the pull request that the call targets a retired model and leaves rewriting it to a separate task.

The rest moves in groups. streamlit and openai go first, together, since the tests exercise both; then anthropic, trubrics, streamlit-feedback and duckduckgo-search, which the tests only import; then the dev tools, whose bumps change what black and mypy complain about rather than what runs, with pre-commit run --all-files as their check. After each group the agent runs pytest -v, ruff check . and an AppTest start of all six scripts. A group that passes is a commit; a group that fails is reverted and its error kept. The edited requirements.txt keeps the file's style, raising a range's floor only where the code needs the newer API and leaving exact pins exact.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Upgrade this Streamlit app's Python dependencies with pip in groups: streamlit and openai together, then the other runtime packages, then the dev tools in requirements-dev.txt, then each exact-pinned package on its own. Keep langchain and langchain-community in step; if moving them needs import changes in the pages or in app_test.py, make that port in its own commit and keep it only if everything passes. After each group run pytest -v, ruff check ., and start every script with streamlit.testing.v1.AppTest and assert no exception. Keep a group only if everything passes; otherwise revert it and record the error. Edit requirements.txt and requirements-dev.txt in their existing style. Open one pull request with one commit per group, one line per bump with old and new versions, and every upgrade left out with the reason.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
  1. Get an API key. In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
  2. Send the request. POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
  3. Read what came back. Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

What comes back

What comes back is a pull request that changes requirements.txt and requirements-dev.txt, in one commit per group that passed, plus a separate commit for the LangChain port if it succeeded, touching the three pages that import from langchain and the patch target in app_test.py. Nothing else in the app changes.

The description lists each bump with the version pip resolved before and after, the upgrades left out with the import error or failing assertion that excluded them, and the result lines of pytest -v, ruff check . and the AppTest start of each script. The trajectory keeps the full output for every group, including the reverted ones.

Before merging, a reviewer checks that langchain and langchain-community moved together or not at all, that a range pin was raised only where the description names the API that needed it, and that the File Q&A page's note about the retired model is tracked somewhere rather than lost.

Run it on every Monday morning

Create an automation in the Project with this prompt and a schedule trigger (cron 0 9 * * 1 in your timezone). Each week the run opens one pull request with that week's bumps, or none when nothing moved. Because each group is its own commit, dropping one bump before merge is a revert of one commit.

To have the link reach your server, start the weekly run from your own scheduler instead, with POST /o/{org}/sessions and an API key that has a webhook URL: Rush then POSTs run.completed with the session_url when the turn ends, and a handler on your side can post the pull request link where the app's maintainers read. A run in which no group passed opens no pull request and says why in its result.

The use case this job follows, with its automation and trigger: Upgrade dependencies weekly.

Why run it on Rush?

A Streamlit app with range pins and no lockfile drifts silently: a fresh deploy picks up whatever pip resolves, and the first sign of a breaking LangChain release is a page that fails to import in production. On Rush the agent resolves the new set in a sandbox, runs the AppTest suite and starts every page after each group, reverts what fails, and keeps the output, so the pull request that reaches you already passed and the failures are written down.

Starting six scripts headless under AppTest after every group is the kind of check a bot pull request never does. The record shows each start and its result, and the same request runs on every Streamlit app you maintain at once.

Frequently asked questions

The tests mock the model calls. How does it know an upgrade works?

The tests prove imports, widget wiring and the response path. The agent adds a start of every script under AppTest, which catches an import that moved or a widget argument that was removed. A model call that only fails with a real key is outside what the sandbox can prove, and the pull request says so.

Will it move LangChain off 0.0.350?

Only in its own commit and only if the port passes. The pages import ChatOpenAI, OpenAI, DuckDuckGoSearchRun and StreamlitCallbackHandler from the old top-level paths, and app_test.py patches one of them. Moving the pair means changing those imports and the patch target; if that works, the commit stays, and if not, the pair stays pinned and the error is in the description.

There is no lockfile. What does the pull request pin?

It edits the files as they are: a range stays a range, with its floor raised only where the code needs the newer API, and an exact pin stays exact at the new version. The resolved versions the suite passed with are in the description so a reader can reproduce the set.

Does it run on Python 3.11 like CI?

Yes. The workflow pins python-version: '3.11', so the sandbox uses 3.11 to resolve and test, and an upgrade that drops 3.11 support is left out with that reason.

Can I exclude a package?

Name it in the prompt and the agent leaves it at its current pin and says so. Packages that need a real API key to exercise, like trubrics, are candidates to exclude if their import check is not enough for you.