Streamlit 1.42.2
I’m trying to fix up anthropic-quickstarts/computer-use-demo at main · anthropics/anthropic-quickstarts · GitHub
This is a toy that demonstrates using Anthropic’s Claude LLM + tool-use to administer a dockerized Ubuntu.
The human interacts with the agent via Streamlit from the host-box (thru an exposed port). A human message starts an “interaction-loop” which keeps going until either (a) the LLM_response.stop_reason == “end_turn” or (b) the user hits the STOP button on streamlit UI’s top-panel.
This STOP button is proving an implementation nightmare!
The original authors failed to handle it properly (it would crash the convo). Now 6 months later they’ve pushed a ghastly botch-fix.
I’m trying to sort it out, but it’s proving painful.
If ONLY there were some option to make this STOP button set a flag instead of triggering a StopException, life would be 100x easier.
Suppose in an interaction-loop the bash-tool is executing a long-running bash command and I hit the STOP button.
AFAICS two things happen:
- the streamlit server re-runs my .py (streamlit.py in my case)
- it sets an internal flag that will raise a StopException at the next “interrupt-point” (seems like things like st.write, st.button
The old script, meanwhile, continues running.
There’s no easy way for my running-bash-command to KNOW that this STOP-button got pressed. Best I can do is have it create a /tmp/.status file containing ‘running’ before it runs, then DURING run it checks the contents and quits out if they’ve changed. Then the new streamlit.py run tweaks the contents if the file exists.
ok so that problem’s solved.
But now a StopException’s gona hit the old code while it’s doing necessary cleanup work to end the interaction.
And this one’s fierce. I’m having to resort to dumping a .json and quitting (before the StopException has a chance to hit). And the new run has to wait for the .json and do the work.
Now I’m having issues with getting the UI components to render upon reflow. Much of the problem is that I have to perform scientific experiments to determine the behaviour of Streamlit w.r.t. reflows.
And it seems I can’t remove this STOP button nor can I rewire it to NOT deliver this StopException.
And the doc-repo (GitHub - streamlit/docs: Source code for the Streamlit Python library documentation) doesn’t even MENTION it – I have to dig thru the source-code to see what’s going on.
I’ve looked at mechanisms of persistence that would allow the main execution to run shielded from the StopException. But no luck. It’s a tangle. st.session_state holds per-tab data, but can only contain serializable-stuff since it’s shuttled between the webpage’s .js environment and the backend. There’s a cache var that doesn’t suffer this serialization-limitation, but that’s global. And if my background-running code does st.text
or something, which tab is that getting applied to? I could cache a dict of runtimes (one for each tab) and each runtime could import streamlit as st
maybe? but this is pure hackery at this point, and no way to develop software.
TLDR Streamlit + LLM-AgentWare devolves into a “round-peg / square-hole” situation. I’ve lost 10 days trying to fix this, and wrote a fresh UI + decoupled-agentLoop in 5 days.
For some reason (stubbornness?) I still want to make this work. I like the Streamlit UI, and want to try to rescue this computer-use-demo project.