API Reference

class redel.ReDel(
*,
root_engine: BaseEngine | None = None,
delegate_engine: BaseEngine | None = None,
root_system_prompt: str | None = DEFAULT_ROOT_PROMPT,
root_kani_kwargs: dict | None = None,
delegate_system_prompt: str | None = DEFAULT_DELEGATE_PROMPT,
delegate_kani_kwargs: dict | None = None,
delegation_scheme: type | None = DelegateWait,
max_delegation_depth: int = 8,
tool_configs: dict[type[_ToolBaseT], ToolConfig] | None = None,
root_has_tools: bool = False,
title: str | AutogenerateTitle | None = AUTOGENERATE_TITLE,
log_dir: Path | None = None,
clear_existing_log: bool = False,
session_id: str | None = None,
)[source]

This class represents a single session of a recursive multi-agent system.

It’s responsible for:

  • all delegation configuration options

  • all the spawned kani and their relations within the session

  • dispatching all events from the session

  • logging events

All arguments to the constructor are keyword arguments.

Parameters:
  • root_engine – The engine to use for the root kani. Requires function calling. (default: gpt-4o) See Engines for a list of available engines and their capabilities.

  • delegate_engine – The engine to use for each delegate kani. Requires function calling. (default: gpt-4o) See Engines for a list of available engines and their capabilities.

  • root_system_prompt – The system prompt for the root kani. See redel.kanis for default.

  • root_kani_kwargs – Additional keyword args to pass to kani.Kani.

  • delegate_system_prompt – The system prompt for the each delegate kani. See redel.kanis for default.

  • delegate_kani_kwargs – Additional keyword args to pass to kani.Kani.

  • delegation_scheme – A class that each kani capable of delegation will use to provide the delegation tool. See redel.delegation for examples. Can be None to disable delegation.

  • max_delegation_depth – The maximum delegation depth. Kanis created at this depth will not inherit from the delegation_scheme class.

  • tool_configs – A mapping of tool mixin classes to their configurations (see ToolConfig).

  • root_has_tools – Whether the root kani should have access to the configured tools (default False).

  • title – The title of this session. Set to redel.AUTOGENERATE_TITLE to automatically generate one (default), or None to disable title generation.

  • log_dir – A path to a directory to save logs for this session. Defaults to $REDEL_HOME/instances/{session_id}/ (default ~/.redel/instances/{session_id}).

  • clear_existing_log – If the log directory has existing events, clear them before writing new events. Otherwise, append to existing events.

  • session_id – The ID of this session. Generally this should not be set manually; it is used for loading previous states.

kanis: dict[str, BaseKani]

A mapping of ID to BaseKani of all the kanis in the system, regardless of tree depth.

root_kani: ReDelKani | None

A reference to the root node. Guaranteed to exist after query() or chat_in_terminal() is called; can be None before then.

get_config(**kwargs)[source]

Get a dictionary with arguments suitable for passing to a ReDel constructor to create a new instance with mostly the same configuration.

By default, the title, log_dir, and session_id will not be copied. Explicitly set these as keyword arguments if you want to copy them.

Pass keyword arguments to override existing configuration options (valid arguments are same as constructor).

async chat_in_terminal()[source]

Chat with the defined system in the terminal. Prints function calls and root messages to the terminal.

async query(query: str) AsyncIterable[BaseEvent][source]

Run one round with the given query.

Yields all loggable events from the app (i.e. no stream deltas) during the query. To get only messages from the root, filter for events.RootMessage.

dispatch(event: BaseEvent)[source]

Dispatch an event to all listeners. Technically this just adds it to a queue and then an async background task dispatches it.

add_listener(callback: Callable[[BaseEvent], Awaitable[Any]])[source]

Add a listener which is called for every event dispatched by the system. The listener must be an asynchronous function that takes in an event in a single argument.

remove_listener(callback)[source]

Remove a listener added by add_listener().

async close()[source]

Clean up all the app resources.

class redel.ToolConfig[source]

A tool’s config should be a dictionary with any of the following keys:

always_include: bool

If true, each delegate kani will always have access to this tool. Defaults to False.

always_include_root: bool

If true, the root kani will have access to this tool (but not necessarily delegates unless always_include is also set).

kwargs: dict

Keyword arguments to pass to the constructor of this class. Defaults to {}.

The tool class’ constructor will be called each time a new instance is bound to a new kani. Each kani will have its own instance of the tool.

class redel.ToolBase(app: ReDel, kani: ReDelKani)[source]

This class is a base that all tool implementations should inherit from.

It provides an interface to the tools in the group to access the application it’s running in (for emitting events) and the kani it’s bound to (for access to the chat state), as well as common setup/teardown hooks.

app: ReDel

The app session this tool is running in.

kani: ReDelKani

The kani this tool is bound to.

async setup()[source]

Called once per bound instance in an async context for each time this tool is bound to a new kani.

Override this method to perform any necessary async setup.

async cleanup()[source]

Called each time the kani this tool is bound to completes its task.

Override this method to clean up any ephemeral chat round-scoped resources if needed, but maintain any other state as the bound kani might still run again.

async close()[source]

Called once per bound instance when the app closes the session.

Override this method to gracefully clean up all resources attached to this tool.

class redel.DelegationBase(app: ReDel, kani: ReDelKani)[source]

This class is a base that all delegation implementations should inherit from.

It extends ToolBase with an interface for creating delegate kani instances.

async create_delegate_kani(instructions: str) ReDelKani[source]

Call this method to get a fresh ReDelKani instance.

This method will handle setting up the new kani in the computation graph as well as its tools, engine, and always included prompt based on the app configuration. It will not launch the kani with the given instructions – this must be done by the calling function.

The calling function is thus responsible for:

  • Setting the state of the calling kani

  • Providing the instructions to the delegate kani and calling its full_round_stream method

  • Buffering the delegate’s response and returning it to the caller

  • Calling the appropriate cleanup methods of the delegate

class redel.state.RunState(value)[source]
  • RunState.STOPPED: This kani is not currently running anything or waiting on a child.

  • RunState.RUNNING: This kani is currently generating text.

  • RunState.WAITING: This kani is waiting for the results of a sub-kani.

  • RunState.ERRORED: This kani has run into a fatal error. Its internal state is indeterminate.

class redel.state.AIFunctionState(
*,
name: str,
desc: str,
auto_retry: bool,
auto_truncate: int | None,
after: ChatRole,
json_schema: dict,
)[source]

Default Events

Most events contain an id attribute, which refers to the ID of the kani that the event refers to.

class redel.BaseEvent(*, type: str, timestamp: float = None)[source]

The base event that all other events should inherit from.

class redel.events.KaniSpawn(
*,
type: Literal['kani_spawn'] = 'kani_spawn',
timestamp: float = None,
id: str,
depth: int,
parent: str | None,
children: list[str],
always_included_messages: list[ChatMessage],
chat_history: list[ChatMessage],
state: RunState,
name: str,
engine_type: str,
engine_repr: str = '',
functions: list[AIFunctionState],
)[source]

A new kani was spawned. Includes the state of the kani. See BaseKani.

The ID can be the same as an existing ID, in which case this event should overwrite the previous state.

class redel.events.KaniStateChange(
*,
type: Literal['kani_state_change'] = 'kani_state_change',
timestamp: float = None,
id: str,
state: RunState,
)[source]

A kani’s run state changed.

This is primarily used for rendering the color of a node in the web interface.

class redel.events.TokensUsed(
*,
type: Literal['tokens_used'] = 'tokens_used',
timestamp: float = None,
id: str,
prompt_tokens: int,
completion_tokens: int,
)[source]

A kani just finished a request to the engine, which used this many tokens.

class redel.events.KaniMessage(
*,
type: Literal['kani_message'] = 'kani_message',
timestamp: float = None,
id: str,
msg: ChatMessage,
)[source]

A kani added a message to its chat history.

class redel.events.RootMessage(
*,
type: Literal['root_message'] = 'root_message',
timestamp: float = None,
msg: ChatMessage,
)[source]

The root kani has a new result.

This will be fired in addition to a kani_message event.

class redel.events.RoundComplete(*, type: Literal['round_complete'] = 'round_complete', timestamp: float = None, session_id: str)[source]

The root kani has finished a full round and control should be handed off to the user.

Visualizer

class redel.server.VizServer(
redel_proto: ReDel | None = None,
/,
*,
save_dirs: Collection[Path] = (DEFAULT_LOG_DIR,),
redel_factory: Callable[[], Awaitable[ReDel]] | None = None,
)[source]
Parameters:
  • redel_proto – If passed, interactive sessions will use the same configuration as the given prototype. Mutually exclusive with redel_factory.

  • save_dirs – A list of paths to scan for ReDel saves to make available to load. Defaults to ~/.redel/instances/.

  • redel_factory – An asynchronous function that creates a new ReDel instance when called. If this is set, redel_proto must not be set.

serve(host='127.0.0.1', port=8000, **kwargs)[source]

Serve this server at the given IP and port. Blocks until interrupted.

Utilities

redel.embeddings.get_embeddings(qs: list[str], model: str) list[EmbeddingResult][source]

Get the embeddings for the inputs, caching them.

class redel.embeddings.EmbeddingResult(idx: int, embedding: numpy.ndarray)[source]
idx: int

The index of the input text in its input list.

embedding: ndarray

The embedding returned by the server (an array of floats).

class redel.utils.AutogenerateTitle[source]

A sentinel class to tell ReDel to automatically generate a session title.

Do not construct manually - use the singleton redel.AUTOGENERATE_TITLE.

redel.utils.read_jsonl(fp) Iterable[dict][source]

Yield JSON objects from the JSONL file at the given path.

Note

This function returns an iterator, not a list – to read a full JSONL file into memory, use list(read_jsonl(...)).

Bundled Tools

class redel.tools.browsing.Browsing(*args, long_engine: BaseEngine | None = None, max_webpage_len: int | None = None, **kwargs)[source]

A tool that provides tools to search Google and visit webpages.

Renders webpages in Markdown and has basic support for reading PDFs.

async search(query: str)[source]

Search a query on Google.

async visit_page(href: str)[source]

Visit a web page and view its contents.

class redel.tools.email.Email(*args, email_from: str, smtp_host: str, smtp_pass: str, **kwargs)[source]

A toy tool to send emails via a given SMTP server.

Parameters:
  • email_from – the email address to send email from

  • smtp_host – a string like mailserv.zhu.codes:465

  • smtp_pass – the password for the email account on the SMTP server

send_email(to: str, subject: str, body: str)[source]

Send an email to the given address.

Bundled Delegation Schemes

class redel.delegation.delegate_one.DelegateOne(app: ReDel, kani: ReDelKani)[source]

Delegate and immediately wait for the result of the sub-agent. Can be called in parallel to run multiple sub-agents in parallel.

async delegate(instructions: ~typing.Annotated[str, <kani.ai_function.AIParam object at 0x7fe449abbdf0>])[source]

Ask a capable helper for help looking up a piece of information or performing an action. Do not simply repeat what the user said as instructions. You should use this to break up complex user queries into multiple simpler steps. NOTE: Helpers cannot see previous parts of your conversation.

class redel.delegation.delegate_and_wait.DelegateWait(*args, **kwargs)[source]

Does not immediately wait for a sub-agent after delegating a task; agents must be explicitly waited by using wait() instead. This lets models without the ability to perform parallel function calling spawn multiple agents in parallel by calling delegate() multiple times before calling wait().

async delegate(instructions: ~typing.Annotated[str, <kani.ai_function.AIParam object at 0x7fe449abb610>], who: ~typing.Annotated[str, <kani.ai_function.AIParam object at 0x7fe449ab8040>] | None = None)[source]

Ask a capable helper for help looking up a piece of information or performing an action. Use wait() to get a helper’s result. You can call this multiple times to take multiple actions. You should break up user queries into multiple smaller queries if possible. Do not delegate the entire task you were given. If the user’s query can be resolved in parallel, call this multiple times then use wait(“all”).

async wait(until: ~typing.Annotated[str, <kani.ai_function.AIParam object at 0x7fe449ab8130>])[source]

Wait for a helper to finish their task and get their result.

Internals

class redel.base_kani.BaseKani(
*args,
app: ReDel,
parent: BaseKani = None,
id: str = None,
name: str = None,
dispatch_creation: bool = True,
**kwargs,
)[source]

Base class for all kani in the application, regardless of recursive delegation.

Extends kani.Kani. See the Kani documentation for more details on the internal chat state and LLM interface.

Parameters:
  • app – The ReDel instance this kani is a part of.

  • parent – The parent of this kani, or None if this is the root of a system.

  • id – The internal ID of this kani. If not passed, generates a UUID.

  • name – The human-readable name of this kani. If not passed, uses the ID.

  • dispatch_creation – Whether to dispatch a events.KaniSpawn event automatically. If false, the caller is responsible for calling app.on_kani_creation() to dispatch the event.

state: RunState

The run state of this kani.

  • RunState.STOPPED: This kani is not currently running anything or waiting on a child.

  • RunState.RUNNING: This kani is currently generating text.

  • RunState.WAITING: This kani is waiting for the results of a sub-kani.

  • RunState.ERRORED: This kani has run into a fatal error. Its internal state is indeterminate.

depth: int

How deep in the computation tree this kani is. Will be 0 for the root node, 1 for children of the root, etc.

parent: BaseKani | None

The parent of this kani, if it is not the root.

children: dict[str, BaseKani]

A mapping of kani ids to kanis of all the immediate children of this kani.

id: str

The internal ID of this kani.

name: str

The human-readable name given to this kani.

app: ReDel

A reference to the ReDel session this kani is running in.

property last_user_message: ChatMessage | None

The most recent USER message in this kani’s chat history, if one exists.

property last_assistant_message: ChatMessage | None

The most recent ASSISTANT message in this kani’s chat history, if one exists.

set_run_state(state: RunState)[source]

Set the run state and dispatch the event.

run_state(state: RunState)[source]

Run the body of this statement with a different run state then set it back after.

async cleanup()[source]

This kani may run again but is done for now; clean up any ephemeral resources but save its state.

async close()[source]

The application is shutting down and all resources should be gracefully cleaned up.

class redel.kanis.ReDelKani(*args, **kwargs)[source]

Base class for recursive delegation kanis. Extends BaseKani.

This class should not be constructed manually - it is tightly coupled to and managed by the application. You can get a reference to a kani powering an agent in a tool by using ToolBase.kani.

Parameters:
  • app – The ReDel instance this kani is a part of.

  • parent – The parent of this kani, or None if this is the root of a system.

  • id – The internal ID of this kani. If not passed, generates a UUID.

  • name – The human-readable name of this kani. If not passed, uses the ID.

  • dispatch_creation – Whether to dispatch a events.KaniSpawn event automatically. If false, the caller is responsible for calling app.on_kani_creation() to dispatch the event.

get_tool(cls: type[ToolBase]) ToolBase | None[source]

Get the tool from this kani’s list of tools, or None if this kani does not have the given tool class.

async get_prompt() list[ChatMessage][source]

Called each time before asking the LM engine for a completion to generate the chat prompt. Returns a list of messages such that the total token count in the messages is less than (self.max_context_size - self.desired_response_tokens).

Always includes the system prompt plus any always_included_messages at the start of the prompt.

You may override this to get more fine-grained control over what is exposed in the model’s memory at any given call.

async cleanup()[source]

This kani may run again but is done for now; clean up any ephemeral resources but save its state.

async close()[source]

The application is shutting down and all resources should be gracefully cleaned up.