Improving Rowan's API
API as a coequal interface to Rowan's product; what we're changing in v3.0.0 of rowan-python; typed outputs; new workflow API; more agent-friendly features; acknowledging our early partners here
When we started Rowan, we thought that the web-based interface would be how most users interacted with our workflows—and, to date, we’ve been right about this. Rowan’s interface makes it simple to submit calculations and understand the results, which (we think) makes it possible for scientists who aren’t simulation experts to gain insight from our tools. We’ve never wanted Rowan to be a tool just for experts, which is why we’re happy that every semester we get used for undergraduate classes around the globe.
In the 2.5 years since we’ve started, though, a lot has changed. The rise of AI coding tools like Claude Code and Codex has meant that more and more people who don’t identify as professional programmers are building their own scripts and applications: we now regularly talk to lab scientists who are writing their own sophisticated software to automate various tasks. Even for experienced software developers, AI compatibility is critical (as Patrick McKenzie has noted), and we’ve known for months that Rowan’s API is not nearly as mature as it needs to be to integrate nicely with these tools.
In parallel to this, we’ve become quite optimistic about the potential of “AI scientists,” or agentic AI systems, to drive scientific progress. There are considerable advantages to combining LLMs with deterministic simulation-based tools: LLMs can handle unstructured or semi-structured data and troubleshoot simulation errors, all of which are tough for conventional simulation tools, while using benchmarked simulation-based tools makes the AI’s proposals verifiable and auditable (and, we expect, will help to prevent hallucination).
Users of Rowan’s Python API will know that things have been a little difficult to use to date; the functionality is “minimal,” to quote one early user. Today, we’re releasing a major update (v3.0.0) to rowan-python, which makes it significantly easier to build atop Rowan’s API. We now see our API as the second interface to Rowan—coequal in scientific and product importance to our web interface—and we’re committed to making it as easy as possible to use Rowan solely via code.
While committed developers (or LLMs) can skip straight to the repository or the updated API docs, here’s our summary of the big changes.
Typed Outputs
In previous versions of Rowan’s API, we returned workflow data as a giant Python dictionary. This made it tough to easily retrieve and use workflow data: users had to manually navigate and decrypt our internal data-storage format for every workflow. We heard from a lot of users that this was frustrating and made building with Rowan difficult (and we experienced it ourself).
In the new version of Rowan’s API, all workflows now return a dataclass with easy-to-understand properties that match what’s shown through the web interface. This makes it easier to understand what’s going on when and simplifies downstream integrations. Each workflow type has its own result class (ConformerSearchResult, pKaResult, DockingResult, &c), with properties and methods specific to that workflow.
Result objects are typed and have helpful docstrings, making it easier to figure out what’s going on. IDEs will autocomplete available properties and typing help(result), hovering in VSCode, or result? in IPython will show you exactly what’s available. This also makes it easier for AI agents to use Rowan by minimizing the need for large external documentation blocks that fill up context windows. (Tough luck for nvim users like Corin, though.)1
Here’s what this looks like in practice:
Old Return
workflow.wait_for_result()
print(workflow.data)
# {'uuid': 'abc123', 'calculations': [{'uuid': 'def456', 'molecule': {'atomic_numbers': [6, 6, 8, ...], 'positions': [[0.0, 0.0, 0.0], ...], 'energy': -2931.662913, 'charges': [0.12,
-0.34, ...], 'multiplicity': 1, 'charge': 0, ...}, 'method': 'aimnet2_wb97md3', 'tasks': ['optimize'], ...}], 'status': 'completed_ok', ...}
energy = workflow.data["calculations"][-1]["molecule"]["energy"]
charges = workflow.data["calculations"][-1]["molecule"]["charges"]New Return
result = workflow.result()
print(result)
# <MultiStageOptResult energy=-2931.662913 H>
energy = result.energy
charges = result.chargesPythonic Workflow API
We’ve also improved how workflow objects are structured in rowan-python. As before, every workflow has a dedicated submit() function that allows users to tune the input options (matching the “Submit” page on the web interface). These functions return a Workflow object, which now has a variety of useful methods following the concurrent.futures.Future pattern.
fetch_latest()loads data from the database and returns an updatedWorkflow(or updates the current object in-place).update()allows users to modify workflows: renaming, sharing, moving folders, email notifications, and so on.stop()allows users to stop running workflows, whiledelete()allows users to delete them.done()checks if the workflow is done.result()returns the workflow’s result object—if the workflow is not finished, the method will by default wait until the result is ready, checking every 5 seconds, although this can be tuned.stream_result()polls the workflow and returns partial results until the final result is ready.
The recommended default pattern is now workflow.result(), which waits for the workflow to finish and returns the aforementioned typed result object. This replaces the old verbose wait_for_result().fetch_latest(in_place=True) pattern.
These new methods make it simple to write scripts that used to be complicated. For instance, here’s a calculation that runs an optimization and updates the user every few seconds on the optimization’s progress:
from stjames import Method, Molecule
import rowan
rowan.api_key = "rowan-sk-your-key-here"
big_smiles = "CC1=C2[C@H](C(=O)[C@@]3([C@@H](C[C@@H]4[C@](C3[C@@H]([C@@](C2(C)C)(C[C@@H]1OC(=O)[C@@H]([C@H](C5=CC=CC=C5)NC(=O)C6=CC=CC=C6)O)O)OC(=O)C7=CC=CC=C7)(CO4)OC(=O)C)O)C)OC(=O)C"
workflow = rowan.submit_basic_calculation_workflow(
initial_molecule=Molecule.from_smiles(big_smiles),
method=Method.AIMNET2_WB97MD3,
tasks=["optimize"],
name="test optimization",
folder=rowan.get_folder("api_examples")
)
print(f"View workflow privately at: <https://labs.rowansci.com/calculation/{workflow.uuid}>")
# previously:
# workflow.wait_for_result()
# energy = workflow.data["calculations"][-1]["molecule"]["energy"]
# now, stream optimization steps as they complete; final iteration is the complete result.
for result in workflow.stream_result(poll_interval=5):
if result.calculation_uuid:
mols = rowan.retrieve_calculation_molecules(result.calculation_uuid)
print(f" {len(mols)} opt steps, energy={mols[-1].get('energy') if mols else None}")
print(result) # <BasicCalculationResult energy=-2931.662913 H>We’ve updated all examples to use the new typed result API. If you’re looking for a quick reference on any workflow, the examples directory in our public GitHub repo has been fully updated—we’ll be moving these examples into a more web- and agent-searchable format soon.
Coming Soon
We’re planning substantial future improvements to our API for code ergonomics and AI agent usage. Here’s some of what we plan to add:
Usage Predictions. Before submitting a workflow, we want to offer estimates for queue time, runtime, and credit cost. (We’ve already added some of this on the web interface; it’s just a matter of porting it over to the API.)
Webhooks. Adding webhooks will allow for notifications when jobs complete (instead of requiring polling), simplifying integration in complex reasoning environments.
Guides and Skills. We’re planning to write documentation specifically for AI agents so that it’s simple to build atop Rowan with no previous experience.
Improved Error Messages. When things fail, you (or your agent) need to be able to understand what went wrong and how you can fix it. We plan to improve end-to-end error messages and increase observability to make it easier to troubleshoot simulation issues.
CLI. We also plan to build a command-line interface so you can submit and monitor Rowan workflows directly from your terminal.
If any of these are particularly important to your work, we’d love to hear from you! Feel free to reach out or open a GitHub issue.
Building Tooling For AI Scientists
As we work to make Rowan more agent-compatible, we’re excited to be building with two early partners in this space.
bioArena
Kat and the team at bioArena started working on integrating Rowan into agentic workflows before we had even considered this area. We’ve been grateful for their support and continual benchmarking of the latest models, tools, & Rowan features, and we’re happy to continue sponsoring the bioArena agentic biology hackathons. (The latest hackathon, focused on designing TREM2 binders, is expected to have in vitro results from Adaptyv next week!)
Mirror Physics
Mirror Physics is building Axon, an interactive agent for drug discovery that orchestrates industry-leading drug-discovery tools to supercharge medicinal chemistry teams. We’re excited to partner with the team at Mirror Physics to give Axon access to Rowan’s tools: you can see early demos of our integration on their Substack, and we look forward to building more sophisticated and performant features alongside their team to drive real value in early-stage campaigns.
We’re excited to explore integration of Rowan into even more AI-powered workflows. If you’re interested in building with Rowan, please reach out! We’re very interested in meeting any builders in this space, from small startups to teams inside large pharmaceutical or materials companies, and we want to make Rowan’s tools as useful as possible to the next generation of AI-powered companies.
Corin here: my coworkers say there are “numerous documentation viewing plugins” that can solve this problem for me. Heresy!





