The OS enforces the rules, not the prompt
Commands that only read run instantly — on macOS and Linux, inside an operating-system sandbox that physically cannot write to your disk. Even if the AI is tricked, the sandbox is not.
Open source · MIT licensed
Calling a provider's raw API is easy. Turning that into a real agent — one that calls tools, remembers a conversation, knows what it costs, and doesn't loop forever — is a week of plumbing every team ends up rebuilding. VisvoAI is that plumbing, published.
pip install visvoaiMost coding agents run on politeness — a prompt that says "please ask before deleting things." That conviction, applied three times:
Commands that only read run instantly — on macOS and Linux, inside an operating-system sandbox that physically cannot write to your disk. Even if the AI is tricked, the sandbox is not.
Agents, skills, and tools that a repo defines stay off until you approve them once — and if the file changes later, you're asked again.
Every agent product needs the same core loop, and most teams rebuild it badly once. Ours is here, tested by two real products, for the next person building their own.
Same call, same model — provider pricing tracked and updated for you instead of hardcoded and going stale. Real code on both sides.
from google import genai
client = genai.Client(api_key="...")
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="Explain attention in one sentence.",
)
# pricing isn't in the SDK — hardcode
# it, and keep it updated by hand
IN_COST = 0.30 # $ / million input tokens
OUT_COST = 2.50 # $ / million output tokens
u = response.usage_metadata
cost = (
u.prompt_token_count / 1e6 * IN_COST
+ u.candidates_token_count / 1e6 * OUT_COST
)from visvoai.ai import build_chat_model
from visvoai.ai import cost_of, usage_from
model = build_chat_model("gemini:gemini-2.5-flash")
response = model.invoke(
"Explain attention in one sentence."
)
u = usage_from(response)
cost = cost_of(
"gemini:gemini-2.5-flash", u["input"], u["output"]
)Switch to Claude or GPT and the left side is a different SDK, different response shape, different pricing lookup entirely. The right side is the same three lines with a different id.
LangGraph's create_react_agenthelper covers the demo case. The moment you need a step budget the model can't talk its way past, you're back to wiring the graph yourself — and re-solving the same recursion problem on every project.
from langgraph.graph import StateGraph, MessagesState
from langgraph.prebuilt import ToolNode, tools_condition
MAX_STEPS = 25
model_with_tools = model.bind_tools(tools)
class State(MessagesState):
steps: int
def call_model(state: State):
steps = state["steps"] + 1
if steps >= MAX_STEPS:
# drop tools so the model is forced to answer —
# easy to get wrong: forget this and a model that
# wants one more tool call just loops forever
reply = model.invoke(state["messages"])
else:
reply = model_with_tools.invoke(state["messages"])
return {"messages": [reply], "steps": steps}
builder = StateGraph(State)
builder.add_node("agent", call_model)
builder.add_node("tools", ToolNode(tools))
builder.add_edge("__start__", "agent")
builder.add_conditional_edges("agent", tools_condition)
builder.add_edge("tools", "agent")
graph = builder.compile()
result = graph.invoke({"messages": [("user", query)], "steps": 0})from visvoai.core.runtime import AgentRuntime
from visvoai.core import ask
graph = AgentRuntime().build_graph(
model=model,
core_tools=tools,
system_prompt="You are a code assistant.",
)
# the step budget, the tools-drop, the retry —
# written once, tested by two shipping products
result = await ask(graph, query)The left side is ~20 lines you write, test, and maintain per project — and it's still missing retrieval for large tool sets. The right side is three.
Use any layer on its own — start wherever your problem is.
One line to any provider's streaming model, plus what most facades skip: a live registry of model facts — pricing, context window, capabilities, normalized thinking levels — so your app can choose and meter models, not just call them.
Providers, registry, metering →from visvoai.ai import build_chat_model, cost_of
model = build_chat_model(
"anthropic:claude-sonnet-4-5",
level="high",
)The loop with a soft step cap (clean final answers, never a recursion error), semantic tool retrieval at fleet scale, a tool lifecycle with pluggable persistence, and extension seams proven by two shipping consumers.
Seams, examples, when-not-to-use →def word_count(text: str) -> int:
"""Count the words in a piece of text."""
return len(text.split())
graph = AgentRuntime().build_graph(
model=model, core_tools=[word_count],
system_prompt="You are ...",
)Not a demo of the toolkit — the same loop and model layer, unmodified, under a full-terminal agent where the permission model is enforced by the OS, not the prompt. Building your own agent product? This is the reference for how far it goes.
Full tour →No API key needed to see the machinery work — the whole loop (retrieval, memory, an audit trail) runs on a scripted model.
pip install visvoai-core "visvoai-ai[gemini]"from visvoai.core import ask
from visvoai.core.runtime import AgentRuntime
graph = AgentRuntime().build_graph(
model=model,
core_tools=[search_docs, file_ticket],
system_prompt="You are our helpdesk bot.",
)
answer = await ask(graph, "how do I reset my password?")Going from zero to a working, multi-provider agent — with a real trust model, not a toy — takes minutes, not the week of SDK-reading and plumbing that calling providers directly usually costs.
Honestly: production hardening — retries across providers, cost caps, shipped observability — is still yours to add today. It's the top of our public roadmap, not a secret. We'd rather tell you what's next than let you find out the hard way.
FAQ