The parts of Urai
Urai has the objects that follow. This page tells you what each object does. The in-app agent guide shows you how to use these objects in sequence.
Organization
Section titled “Organization”The organization is the boundary for billing and for access. These items belong to an organization:
- Model provider credentials
- Git access tokens
- Libraries
- Skills
You get an organization when you sign in for the first time. Each person that you invite joins the organization with a role. Owners and admins can open the credential screens and the member screens. Other roles cannot open these screens.
Project
Section titled “Project”A project is a workspace in an organization. A project holds agents, conversation threads, and notes. Each project has its own member list. Most teams start with one project for each product area.
The agent answers the user. An agent has these properties:
- A model
- System instructions
- Attached libraries
- Skill tags
- Attached knowledge collections
- A JSON
varsobject, which Urai gives to each run
The API and the SDK use the name assistant for this object. Paths start with
/api/assistants/, and payloads contain assistant_id.
An agent runs in one of two modes.
Advanced mode runs a loop that writes code. The agent calls
write(name, code) to save a JavaScript file. The agent then calls
execute(name) to run that file in the uraiJS sandbox. The agent reads the
result and does these steps again until it calls final_answer. An advanced
agent imports your published libraries, and it loads skills by tag.
Each execution starts in a new runtime. The files that the agent saves stay available for the thread, but the variables do not stay available. Three limits control the loop:
- A step limit of 50 steps or fewer
- The allowed-secrets list
- The network allowlist
Simple mode runs a chat loop over a fixed set of remote tools. A simple agent cannot use libraries or skills. Use simple mode when the agent only answers questions.
An agent answers in three places. It answers in the Urai interface, it answers in a widget that you embed, and it answers your own code over the Agents API. Each door runs the same agent. Turn the Agents API on for one agent at a time, because an enabled agent answers any API key in the organization.
Knowledge
Section titled “Knowledge”A collection is a group of documents that you upload. Urai keeps collections in your organization. You attach one or more collections to an agent. You can also name collections in a request to the Chat Completions API.
Urai accepts these file formats:
- DOCX
- PPTX
- Markdown and plain text
Urai extracts the text from each file and makes Markdown from it. Urai then
divides the Markdown into chunks and indexes the chunks. A document has the
status pending, processing, ready, or failed. Only a document with the
status ready is available to search.
Urai searches a collection with two methods at the same time. BM25 finds the documents that contain the words of the query. Vector search finds the documents with a related meaning. Urai then combines the two sets of results. This method is hybrid search, and it finds a document even when the user writes different words from the document.
An agent with one or more collections gets two more tools:
search_documentsreturns the passages that match a query. Each passage carries a citation with the name of the document. The citation also gives the page number for a PDF file or a PPTX file.read_documentreturns the full text of one document. Urai sends a long document in more than one part.
An agent with no collections does not get these two tools. Search knowledge collections shows you how to use the same tools from the Chat Completions API. The Knowledge API gives you the collections and the search on their own, for code that writes its own prompt.
Library
Section titled “Library”A library is reusable TypeScript code. An advanced agent imports a library as
urai:lib/<org>/<name> in the code that it writes. Libraries run in the uraiJS
runtime. This runtime is a sandboxed JavaScript environment, and it is not Node.
A library has fetch, timers, web crypto, and npm imports. It has no filesystem
and no process access.
Write a library with the uraijs CLI. Push the library to the git remote of
your organization to publish it. Then attach the library to an agent in the
agent editor.
The agent does not read your source code. The agent reads AGENT.md from the
library, because Urai puts that file into the prompt. The agent also reads
docs/llms.txt if you publish that file. These two files make the library
usable. Write them with the same care as the code.
Two channels move data in and out of the code that runs:
meta.varsholds the variables of the agent and the context of the conversation. Urai always addsthread_id,organization_id, anduser_id. The secrets that you permit have the namesmeta.secrets.NAME.meta.urai.sendCommand(threadId, payload)sends a message to the browser before the turn is complete. The agent uses this method to tell your application to go to a page or to refresh a view.
A skill is a playbook in Markdown for one task. Urai keeps skills in your organization, and each skill has tags. Each agent has its own list of tags.
The prompt of the agent lists each published skill that has one or more of those
tags. The list shows the name and the description of each skill. The agent calls
load_skill to read the full text when the task occurs. The agent calls
search_skills when the correct skill is not obvious.
Skills change independently of agents. When you publish a skill, or when you change the tags of a skill, your agents get new abilities. You do not edit an agent. A skill has three states:
- Candidate, for a skill in review
- Published, for a skill in live use
- Archived, for a skill that you no longer use
Urai can also write a candidate skill from a conversation that was successful. You then edit that candidate.
Simple agents use a third mechanism: remote tools. A remote tool is an @tool
function that the model calls directly. Advanced agents do not need remote
tools, because they import libraries in the code that they write.
Workflow
Section titled “Workflow”A workflow is durable TypeScript code that runs without a person. Use a workflow when one event starts several operations, and these operations must occur in sequence. Each operation can fail on its own. Compare a workflow with the other two objects: an agent answers a person, and a library does one function call.
You write a workflow as a coordinator class and a set of steps. You push the workflow like a library, then you register it. Registration sets the envelope. The envelope holds these permissions:
- The secrets that a run can read
- The hosts that the workflow declares
- Permission to call a model
- The integration connections that the run uses
The envelope belongs to the workflow. A trigger cannot make the envelope larger.
Runs are durable. The coordinator replays at each tick. The steps that are
complete return their stored results. Urai keeps no connection open between the
ticks. A run can therefore wait at awaitApproval() for one week, and then
continue. Workflows shows the full procedure.
Widget
Section titled “Widget”The widget is the chat interface that your users see. A widget belongs to one agent. A widget holds its own token, allowed origins, theme, layout, and behavior. The theme, the layout, and the behavior are presentation only. You can change the style or the welcome message from the console, and you do not change your application.
Two rules are more important than the other rules:
- The token identifies the widget in public. Use the token as a public identifier. Do not use the token as a secret.
- Urai checks each request against the allowed origins. This check includes the stream that sends the reply. A request from an origin that is not in the list receives a 403 error. Other sites therefore cannot use your widget. This rule is not authentication.
The visitor id that your page sends is opaque text. Urai does not compare this text with a user table. Vars come from the browser. The visitor id and the vars cannot carry authorization. Securing your app tells you what to do.
The flow of a message
Section titled “The flow of a message”These steps occur when a visitor sends a message:
- The visitor types a message in the widget.
- The widget sends the message to the chat service. The widget also sends its token, the visitor id that you supply, and the vars for that thread.
- The agent runs, and it calls its tools. Each tool receives those vars.
- A tool can send a command on the open stream.
- The reply goes to the widget in small parts.
- Your page receives each command as an event, and your code can act on that event.