# WaveAssist > The deterministic agent runtime. Describe a recurring job in plain English; your > coding agent builds it over MCP, and WaveAssist runs it in the cloud on your > schedule, the same way every run, only after it proves it works. Intelligence is > contained to wrapped, schema-locked model calls (call_llm + a Pydantic > response_model), so every run returns the same structure. $2 of runtime credit > comes with every account. ## Pages - [Home](https://waveassist.ai/): The deterministic agent runtime. Connect over MCP, describe a job, run it on a schedule. - [Platform](https://waveassist.ai/platform): How WaveAssist works: a codified pipeline wrapped around schema-locked model calls, run on a schedule, armed only after a passing run. - [Connect the MCP](https://waveassist.ai/mcp): Connect from Claude Code, Cursor, or any MCP host. Get your rotatable MCP token and pricing here; $2 of runtime credit comes with every account. - [Gallery](https://waveassist.ai/gallery): Agents running on WaveAssist, generalized from real deployments: code review, forecasting, verification, reporting, monitoring, and more. - [Blog](https://waveassist.ai/blog): Notes on deterministic agents, how the runtime works, and the architecture behind production AI. - [Contact](https://waveassist.ai/contact): Get in touch. No sales funnel, no demo call, just a message. ## Docs - [Agent over MCP](https://waveassist.ai/docs): Connect over MCP, hand your coding agent a token, describe a job in plain English, and it ships a scheduled agent. - [SDK](https://waveassist.ai/docs/sdk): The waveassist Python SDK: install, the run() entry point, state with fetch_data/store_data, schema-locked intelligence with call_llm, and output helpers. - [API reference](https://waveassist.ai/docs/api): Function reference for the waveassist runtime: init, store_data, fetch_data, call_llm, send_email, publish_dashboard, and more. ## Blog - [Coding Didn't Die. Prompting Became Coding.](https://waveassist.ai/blog/coding-didnt-die-prompting-became-coding): AI didn't kill the coder. Making AI do something useful quietly became coding: decomposition, contracts, tests, structure. - [Deterministic vs Agentic: The Quiet Architectural Bet Every AI Agent Company Is Making](https://waveassist.ai/blog/deterministic-vs-agentic-ai-agents): Fat harness rethinks every step at runtime; thin harness designs the pipeline once, then code runs forever. Most production agents are thin. - [You Can't Nudge a Painting: The Two Shapes of AI Output](https://waveassist.ai/blog/you-cant-nudge-a-painting): Painting-shape output is finished and freeform; blueprint-shape is structured and editable. WaveAssist builds blueprints. ## Legal - [Privacy Policy](https://waveassist.ai/legal/privacy): How WaveAssist Technologies Pvt Ltd collects, uses, and protects your data. - [Terms of Service](https://waveassist.ai/legal/terms): The terms governing use of WaveAssist. ## Connect (MCP) - Endpoint: https://mcp.waveassist.ai/mcp - Auth header: Authorization: Bearer YOUR_TOKEN - Get your rotatable MCP token from the Connect MCP panel at https://app.waveassist.io - $2 of runtime credit comes with every account. ## Install pip install waveassist ## Determinism model - The pipeline is plain Python: fetch, transform, post, persist, schedule. - Model calls go through call_llm(model, prompt, response_model). response_model is a Pydantic class, so output is a typed, schema-locked instance. Content can vary, structure never drifts. - fetch_data / store_data carry state between runs. - Every deploy does a real verify run on live infrastructure and arms the schedule only after it passes. is_test_run() is True during that verify run. ## API init(token=None, project_key=None, environment_key=None, run_id=None, check_credits=False) -> None Initialize the runtime. Resolves from args, env vars, or .env. Call once per node. store_data(key, data, run_based=False, data_type=None) Persist a value. data_type is "string" | "json" | "dataframe" (inferred if omitted). run_based=True scopes the value to the current run. fetch_data(key, run_based=False, default=None) Read a stored value, or default if absent. call_llm(model, prompt, response_model, should_retry=False, **kwargs) -> T Wrapped model call. response_model is a Pydantic BaseModel subclass; returns an instance of it. This is what makes output deterministic in shape. send_email(subject, html_content, attachment_file=None, cc=None, bcc=None, raise_on_failure=True) -> bool Send an HTML email from the agent. publish_dashboard(html_content, data_key="dashboard_html", run_based=False) -> str | None Store an HTML dashboard, return a public shareable URL. check_credits_and_notify(required_credits: float, assistant_name: str) -> bool Verify enough runtime credit before costly work; notify owner if not. fetch_openrouter_credits() -> dict Current project credit balance. mark_run_idle() -> bool Flag the current run as idle (executed but did no meaningful work). Dashboard collapses idle runs into a heartbeat. Absence of the flag means the run did work. is_test_run() -> bool True during a dry/verify run, before the schedule arms. Guard side effects with it. set_worker_defaults(token=None, project_key=None, environment_key=None, run_id=None) -> None set_default_environment_key(key: str) -> None ## Minimal agent from pydantic import BaseModel import waveassist waveassist.init() class Review(BaseModel): summary: str risk: str comments: list[str] def run(): pr = waveassist.fetch_data("pull_request") review = waveassist.call_llm( model="anthropic/claude-haiku-4.5", prompt=review_prompt(pr), response_model=Review, ) post_comment(pr, review) waveassist.store_data("last_review", review, data_type="json")