An agent with ParallelTools couldn't be copied, so every AgentOS request shared one toolkit and its include_domains list. Agno's ParallelTools now defines its own __deepcopy__, which reuses the live Parallel SDK client and copies everything else, so each request gets a toolkit with its own settings.
AgentOS calls deep_copy() on your agent or team for every request. In earlier releases the copy tried to duplicate the SDK's HTTP client and its lock. copy.deepcopy failed, and deep_copy() caught the error and handed back the original toolkit. The half-copied client also printed a warning each time it was garbage collected.
We ran the same script on both releases with ParallelTools(api_key="dummy", include_domains=["example.com"]). It makes no network call:
# real output
# Before
copy.deepcopy(agent): TypeError: cannot pickle '_thread.RLock' object
warning: AttributeError: 'SyncHttpxClientWrapper' object has no attribute '_state'
agent.deep_copy(): copied toolkit=False, same client=True, own include_domains=False
warning: AttributeError: 'SyncHttpxClientWrapper' object has no attribute '_state'
# Now
copy.deepcopy(agent): copied toolkit=True, same client=True, own include_domains=True
agent.deep_copy(): copied toolkit=True, same client=True, own include_domains=TrueSee the cookbook, and learn more about Parallel in the documentation.
Frequently asked questions
The copy tried to duplicate the Parallel SDK HTTP client, which holds a thread lock. copy.deepcopy raised TypeError: cannot pickle '_thread.RLock' object, and the half-built client logged an AttributeError about _state when it was garbage collected.
Yes. AgentOS calls deep_copy() on the agent or team for each request so runs do not share state. With this fix, ParallelTools survives that copy and the copy reuses the original Parallel client.
No. Each copy gets its own settings, such as include_domains, and its tool functions are bound to the copy. Only the live Parallel SDK client is shared.


