Errand AI documentation # Documentation - Self-Hosted AI Task Automation > Complete documentation for Errand AI — installation guides, AI model configuration, integrations, cloud service setup, and architecture. Everything you need to get started with self-hosted AI task automation. ## Quick Start Guides [Section titled “Quick Start Guides”](#quick-start-guides) Featured quick start guides to get up and running fast. [Installation & Setup ](/docs/installation/macos/)Set up your Errand installation on macOS. [Choosing your AI Models ](/docs/ai-models/choosing-models/)Understanding what choices to make when selecting AI models for your tasks. [Connect Cloud Service ](/docs/cloud-service/)Connect Errand Cloud for secure remote access and webhook relay. ## Explore Cloud Service Features [Section titled “Explore Cloud Service Features”](#explore-cloud-service-features) Explore Errand Cloud features for remote access and integrations. [Remote Agent Management ](/docs/cloud-service/remote-management/)Manage your agents remotely and monitor your task dashboard from anywhere. [Integrations ](/docs/cloud-service/webhook-relays/)Connect Slack, GitHub, Jira, Google Drive, OneDrive, and more to your Errand agents. ## Core Concepts [Section titled “Core Concepts”](#core-concepts) Understand how Errand AI works under the hood. [AI Models & Providers ](/docs/ai-models/)Configure Anthropic, OpenAI, Google, or local models via Ollama. [AI Memory ](/docs/ai-memory/)Persistent memory that lets your agents learn and improve over time. [MCP Server ](/docs/mcp-server/)Connect Claude Code, Cursor, or custom agents to Errand as a task backend. [Architecture Overview ](/docs/architecture/overview/)See how the scheduler, workers, and tools fit together. --- # AI Memory > Persisting knowledge for your tasks. AI agents forget everything between sessions. Every conversation starts from zero—no context about who you are, what you’ve discussed, or what the assistant has learned. This is not just an implementation detail; it fundamentally limits what AI Agents can do. There are many approaches to giving AI agents persisted *memory* so that when starting a new task, the agent is provided with the context it needs to be able to complete the task successfully. These range from storing information in a text-based markdown file, such as `CLAUDE.md` or `AGENTS.md`, which the agent is instructed to read at startup, to complex RAG (Retrieval-Augmented Generation) systems that are capable of consuming your entire corporate documentation system and giving the agent a ‘search index’. ## Hindsight [Section titled “Hindsight”](#hindsight) For Errand AI, we have chosed to integrate with [Hindsight](https://hindsight.vectorize.io/). We believe that text-file based memory systems are inefficient and wasteful since the entire file has to be loaded into the agent’s limited context window and will contain information that is not necessary for the completion of the task at hand. Traditional RAG only retrieves documents similar to a query. Hindsight provides structured memory with temporal reasoning, entity understanding, and belief formation. Hindsight uses its own AI model for processing memories. For guidance on choosing the right model, see the [Choosing the Right Models](/docs/ai-models/choosing-models/#the-hindsight-memory-model) guide. If you use the Errand Desktop app to install your Errand service, it will automatically download and configure Hindsight to work with your deployment. --- # AI Models > Understanding and choosing the right AI models for Errand. Errand uses AI models to do its work — reading your task descriptions, reasoning about what needs to be done, calling tools, and producing results. The models you choose have a direct impact on the quality of the work Errand produces, how fast it responds, and how much it costs to run. You do not need to be an AI expert to make good choices here. This guide will walk you through what matters and help you pick the right models for your setup. ## How Errand Uses Models [Section titled “How Errand Uses Models”](#how-errand-uses-models) Errand does not use a single model for everything. Different parts of the system have different needs, so you configure a model for each purpose: ### Agent Model (Default Model) [Section titled “Agent Model (Default Model)”](#agent-model-default-model) This is the most important choice. The agent model powers the main task execution loop — it reads your instructions, decides what to do, calls tools (like web search, email, or file access), and produces the final result. This model needs to be capable of complex, multi-step reasoning and reliable tool use. **Minimum recommended tier: Balanced** (see [Choosing the Right Models](/docs/ai-models/choosing-models/) for details). ### Title Generation Model [Section titled “Title Generation Model”](#title-generation-model) When you create a task, Errand automatically generates a short, descriptive title. This is a simple summarisation job that even lightweight models handle well. **Recommended tier: Efficient.** ### Hindsight Memory Model [Section titled “Hindsight Memory Model”](#hindsight-memory-model) [Hindsight](/docs/ai-memory/) is Errand’s memory system. It uses an AI model to understand, store, and retrieve knowledge across tasks. The model needs good language comprehension, but it does not need the advanced reasoning capabilities required by the agent. **Recommended tier: Efficient to Balanced.** ### Transcription Model (Optional) [Section titled “Transcription Model (Optional)”](#transcription-model-optional) If you want to create tasks using your voice, Errand can transcribe audio input into text. This requires a **Whisper-compatible** model. Leave this unconfigured if you do not plan to use voice input. You can also assign different models to specific types of work using [Task Profiles](/docs/configuration/task-profiles/). For example, you might use a more powerful model for research tasks and a faster one for quick replies. ## Quick-Start Recommendations [Section titled “Quick-Start Recommendations”](#quick-start-recommendations) If you just want to get started, here are our recommendations: | Purpose | Recommended Tier | Example Models | | -------------------- | ---------------- | ----------------------------------------------- | | **Agent (Default)** | Balanced | Claude Sonnet 4, GPT-4o, Gemini 2.5 Flash | | **Title Generation** | Efficient | Claude Haiku 4.5, GPT-4o Mini, Gemini 2.0 Flash | | **Hindsight Memory** | Efficient | Claude Haiku 4.5, GPT-4o Mini, Gemini 2.0 Flash | | **Transcription** | Whisper | whisper-large-v3 (cloud or local) | These are starting points. For a deeper understanding of what each tier means and how to choose, see [Choosing the Right Models](/docs/ai-models/choosing-models/). ## LiteLLM — Your Model Gateway [Section titled “LiteLLM — Your Model Gateway”](#litellm--your-model-gateway) We strongly recommend using [LiteLLM](https://www.litellm.ai/) as a proxy between Errand and your model providers. LiteLLM provides a single, unified API that works with virtually every LLM provider — cloud services, local models, and everything in between. Both Errand and Hindsight connect to your models through LiteLLM. ### Why Use LiteLLM? [Section titled “Why Use LiteLLM?”](#why-use-litellm) * **One interface for everything.** Configure your providers and API keys in LiteLLM once, and both Errand and Hindsight can use any model you have set up. No need to manage credentials in multiple places. * **Switch providers without reconfiguring Errand.** Want to try a different model or provider? Change it in LiteLLM and Errand picks it up automatically. * **Spend tracking and budgets.** Monitor how much you are spending on AI across all providers in one dashboard. * **Rate limiting and fallbacks.** Protect yourself from unexpected costs, and automatically fall back to an alternative model if your primary one is unavailable. * **Guardrails.** Add safety checks and content filtering at the proxy level. ### How It Works [Section titled “How It Works”](#how-it-works) ![Architecture diagram showing Cloud Providers and Local Models connecting through LiteLLM to Errand and Hindsight](/_astro/litellm-architecture.CucZ-bT2_1BJDRK.svg) ### Getting Started with LiteLLM [Section titled “Getting Started with LiteLLM”](#getting-started-with-litellm) If you are using **Errand Desktop**, LiteLLM is included automatically. The setup process will guide you through adding your provider credentials and selecting models before configuring the rest of the system. For **Docker Compose** and **Kubernetes** deployments, LiteLLM is included in the default configuration. See the [Docker installation guide](/docs/installation/docker/) or [Kubernetes installation guide](/docs/installation/kubernetes/) for setup instructions. While LiteLLM is optional — Errand will work with any OpenAI-compatible endpoint — we recommend it for all deployments. The operational benefits are significant, especially as your usage grows. LiteLLM is open source and completely free to use. ## Going Deeper [Section titled “Going Deeper”](#going-deeper) * **[Choosing the Right Models](/docs/ai-models/choosing-models/)** — Understand the capability tiers, what each model slot needs, and how to make trade-offs between quality, speed, and cost. * **[LLM Providers](/docs/ai-models/providers/)** — A guide to the major cloud providers, aggregator services, and how to choose between them. * **[Running Models Locally](/docs/ai-models/local-models/)** — Set up Ollama, vLLM, or other local model servers for privacy, cost savings, or offline use. --- # Choosing the Right Models > How to select the best AI models for each part of Errand. Errand has four model slots, each with different requirements. This page explains what each slot needs, introduces a simple tier system for thinking about model capabilities, and gives you concrete recommendations. ## Model Capability Tiers [Section titled “Model Capability Tiers”](#model-capability-tiers) To make model selection easier, we group models into three capability tiers. These tiers are not official classifications — they are a practical shorthand for thinking about which models are suitable for which tasks. | Tier | What It Means | Current Examples | | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | | **Frontier** | The most capable models available. Best reasoning, most reliable tool use, handles complex multi-step tasks with ease. Higher cost, sometimes slower. | Claude Opus 4, GPT-4.1, Gemini 2.5 Pro | | **Balanced** | Strong all-round performers. Reliable tool use, good reasoning, noticeably faster and more affordable than Frontier models. The sweet spot for most work. | Claude Sonnet 4, GPT-4o, Gemini 2.5 Flash | | **Efficient** | Fast and affordable. Excellent for straightforward tasks like summarisation, classification, and simple text generation. Not suitable for complex multi-step reasoning. | Claude Haiku 4.5, GPT-4o Mini, Gemini 2.0 Flash | Model names change as providers release new versions. The tier a model belongs to matters more than its specific name — when a provider releases a new model, check where it sits in their lineup and map it to the tier above. ## The Agent Model [Section titled “The Agent Model”](#the-agent-model) This is the most important model choice you will make. The agent model runs Errand’s core task execution loop: it reads your instructions, plans what to do, calls tools (web search, email, file access, and more), interprets the results, and produces a final output. ### What the Agent Needs [Section titled “What the Agent Needs”](#what-the-agent-needs) The agent model must be strong in several areas: * **Tool calling.** The agent works by calling external tools — searching the web, sending emails, reading files, managing tasks. The model must reliably generate correctly structured tool calls. This is the single most important capability. * **Multi-step reasoning.** Most tasks require several steps: research a topic, then draft an email, then send it. The model must maintain context and make good decisions across multiple turns. * **Long context window.** The agent receives a system prompt, your task description, tool definitions, recalled memories, and the results of every tool call it makes. This adds up quickly. Models with larger context windows handle complex tasks more gracefully. * **Instruction following.** The agent receives detailed instructions about how to behave, what tools are available, and what format to use for its output. The model must follow these reliably. ### Minimum Recommended: Balanced Tier [Section titled “Minimum Recommended: Balanced Tier”](#minimum-recommended-balanced-tier) We recommend using at least a **Balanced-tier** model for the agent. Here is why: Models below this level — including most Efficient-tier models and smaller open-source models — often struggle with reliable tool calling. In practice, this means: * **Failed tool calls.** The model generates tool calls with incorrect parameters, missing fields, or malformed syntax. The agent gets stuck or produces errors instead of results. * **Lost context.** The model forgets earlier steps in a multi-turn task, repeating work or contradicting its own previous decisions. * **Poor judgement.** The model makes questionable choices about which tools to use or when to stop, leading to incomplete or irrelevant results. * **Wasted time and cost.** A task that fails and needs to be re-run with a better model ends up costing more than using the right model in the first place. Using an Efficient-tier model for the agent is like hiring an intern for a senior role — they might occasionally get it right, but the reliability is not there for work you depend on. ### When to Use a Frontier Model [Section titled “When to Use a Frontier Model”](#when-to-use-a-frontier-model) For most everyday tasks — drafting emails, researching topics, managing to-do lists — a Balanced-tier model is excellent. Consider stepping up to a Frontier model when: * Tasks involve complex reasoning across many steps * You need the highest possible quality for important work * Tasks require synthesising information from many sources * You are doing detailed code review or technical writing You can use [Task Profiles](/docs/configuration/task-profiles/) to assign a Frontier model to specific types of work without changing your default. For example, set up a “Research” profile that uses a Frontier model, while everyday tasks use your Balanced default. ### Trade-Offs [Section titled “Trade-Offs”](#trade-offs) | | Frontier | Balanced | | ------------ | ------------------------- | --------------- | | **Quality** | Best available | Very good | | **Speed** | Slower | Faster | | **Cost** | Higher per task | More affordable | | **Best for** | Complex, high-stakes work | Everyday tasks | Most users find that a **Balanced-tier model as the default**, with a Frontier model available via Task Profiles for demanding work, gives the best overall experience. ## The Title Generation Model [Section titled “The Title Generation Model”](#the-title-generation-model) When you create a task, Errand automatically generates a short, descriptive title from your task description. This is a single-shot summarisation job — the model reads your description and produces a few words. ### Recommended: Efficient Tier [Section titled “Recommended: Efficient Tier”](#recommended-efficient-tier) This is the easiest choice. Even the smallest, most affordable models handle short-text summarisation well. There is no benefit to using a more powerful model here — it would produce the same quality title at higher cost and slower speed. Any Efficient-tier model will do the job. Pick whichever one your provider offers at the lowest cost. ## The Hindsight Memory Model [Section titled “The Hindsight Memory Model”](#the-hindsight-memory-model) [Hindsight](/docs/ai-memory/) is Errand’s persistent memory system. It uses an AI model to: * Extract entities and concepts from your tasks and their results * Form “beliefs” — structured knowledge about your preferences, past decisions, and context * Search and retrieve relevant memories when a new task starts ### Recommended: Efficient to Balanced [Section titled “Recommended: Efficient to Balanced”](#recommended-efficient-to-balanced) The Hindsight model needs good language comprehension — it must understand what is important in a piece of text and extract meaning from it. However, it does not need the multi-step reasoning or tool-calling capabilities that the agent requires. * **Efficient tier** works well for most users. Memories are stored and recalled reliably, and the cost stays low since Hindsight processes text for every task. * **Balanced tier** can provide richer, more nuanced memory extraction if you find that the Efficient model is missing important context. This is a quality-versus-cost decision you can experiment with. Start with an Efficient-tier model and upgrade if you notice the agent is not recalling relevant context from previous tasks. ## The Transcription Model [Section titled “The Transcription Model”](#the-transcription-model) If you want to create tasks by speaking instead of typing, Errand can transcribe your voice input into text. This requires a **Whisper-compatible** transcription model. ### Options [Section titled “Options”](#options) * **Cloud:** OpenAI’s Whisper API, accessed through [LiteLLM](/docs/ai-models/), is the most common choice. Several other providers also offer Whisper-compatible endpoints. * **Local:** You can run Whisper models locally through [Ollama](/docs/ai-models/local-models/) or other local model servers, keeping your audio data entirely on your own hardware. If you do not plan to use voice input, leave the transcription model unconfigured. ## Task Profiles — Per-Task Model Overrides [Section titled “Task Profiles — Per-Task Model Overrides”](#task-profiles--per-task-model-overrides) Errand’s [Task Profiles](/docs/configuration/task-profiles/) feature lets you assign different models to different types of work. Instead of choosing one model for everything, you can create profiles that automatically match tasks to the right model: * A **Research** profile might use a Frontier-tier model with access to web search tools * A **Quick Reply** profile might use an Efficient-tier model for near-instant responses * A **Code Review** profile might use a Frontier-tier model with access to your Git repository Profiles give you flexibility without requiring you to change your default settings every time. See the [Task Profiles documentation](/docs/configuration/task-profiles/) for setup instructions. ## Example Configurations [Section titled “Example Configurations”](#example-configurations) Here are some common setups to help you get started. All models are accessed through [LiteLLM](/docs/ai-models/) regardless of which configuration you choose. ### Best Quality [Section titled “Best Quality”](#best-quality) For users who want the highest quality results and are comfortable with the associated cost. | Slot | Tier | Example | | ---------------- | --------- | ---------------- | | Agent | Frontier | Claude Opus 4 | | Title Generation | Efficient | Claude Haiku 4.5 | | Hindsight | Balanced | Claude Sonnet 4 | | Transcription | Whisper | whisper-large-v3 | ### Balanced (Recommended) [Section titled “Balanced (Recommended)”](#balanced-recommended) The sweet spot for most users — excellent results at a reasonable cost. | Slot | Tier | Example | | ---------------- | --------- | ---------------- | | Agent | Balanced | Claude Sonnet 4 | | Title Generation | Efficient | Claude Haiku 4.5 | | Hindsight | Efficient | GPT-4o Mini | | Transcription | Whisper | whisper-large-v3 | ### Budget-Conscious [Section titled “Budget-Conscious”](#budget-conscious) Keeps costs low while still delivering good agent performance. | Slot | Tier | Example | | ---------------- | --------- | ---------------- | | Agent | Balanced | Gemini 2.5 Flash | | Title Generation | Efficient | Gemini 2.0 Flash | | Hindsight | Efficient | Gemini 2.0 Flash | | Transcription | Whisper | whisper-large-v3 | ### Privacy-First [Section titled “Privacy-First”](#privacy-first) Everything runs on your own hardware. See [Running Models Locally](/docs/ai-models/local-models/) for setup. | Slot | Tier | Example | | ---------------- | ----------------- | ----------------------------- | | Agent | Balanced (local) | Llama 3.3 70B (via Ollama) | | Title Generation | Efficient (local) | Llama 3.2 3B (via Ollama) | | Hindsight | Efficient (local) | Llama 3.2 3B (via Ollama) | | Transcription | Whisper (local) | whisper-large-v3 (via Ollama) | Note that the Privacy-First configuration requires significant hardware — see the [local models guide](/docs/ai-models/local-models/) for requirements. --- # Running Models Locally > How to run AI models on your own hardware for use with Errand. If you want to keep your data entirely on your own hardware, avoid per-token costs, or use Errand without an internet connection, you can run AI models locally. This page covers the main options and helps you set realistic expectations. ## Before You Start [Section titled “Before You Start”](#before-you-start) Running models locally is very different from using a cloud API. Here is what you need to know: ### Hardware Requirements [Section titled “Hardware Requirements”](#hardware-requirements) AI models are computationally demanding. The quality of results you can achieve locally depends directly on the hardware you have available: * **GPU strongly recommended.** Modern AI models run dramatically faster on a GPU. Without one, you will be waiting minutes rather than seconds for each response. For the agent model, a dedicated GPU is effectively a requirement. * **Memory matters.** A model needs to fit in your GPU’s VRAM (or system RAM for CPU inference). Larger models produce better results but need more memory. A 70B parameter model — the minimum we recommend for agent use — typically requires 40GB+ of VRAM. * **Storage.** Model files are large. Expect to download 4-40GB per model depending on size and quantisation. ### Performance Expectations [Section titled “Performance Expectations”](#performance-expectations) Be honest with yourself about what local models can deliver: * **Smaller models are less capable.** A 7B or 13B parameter model is fine for title generation and Hindsight, but it will struggle with the complex tool-calling and multi-step reasoning that the agent needs. See [Choosing the Right Models](/docs/ai-models/choosing-models/) for minimum tier recommendations. * **Slower responses.** Even with good hardware, local inference is generally slower than cloud APIs. This is especially noticeable for the agent model, which makes multiple calls during each task. * **Quality trade-off.** The most capable cloud models (Frontier tier) have no local equivalent. If you need the very best quality, cloud is still the way to get it. None of this means local models are not useful — they absolutely are, especially for the simpler model slots and for the [hybrid approach](#the-hybrid-approach) described below. ## Ollama [Section titled “Ollama”](#ollama) [Ollama](https://ollama.com/) is the easiest way to run models locally. It handles downloading, configuring, and serving models with a simple command-line interface. If you have used Docker, the experience is similar — you pull a model and it just works. ### Getting Started [Section titled “Getting Started”](#getting-started) 1. Install Ollama from [ollama.com](https://ollama.com/) 2. Pull a model: `ollama pull llama3.3:70b` 3. Ollama automatically starts a local API server ### Recommended Models for Errand [Section titled “Recommended Models for Errand”](#recommended-models-for-errand) | Errand Slot | Recommended Model | Size | Notes | | -------------------- | ------------------------------- | ------- | -------------------------------------------------------- | | **Agent** | `llama3.3:70b` or `qwen2.5:72b` | \~40GB | Minimum for reliable tool calling. Needs a powerful GPU. | | **Title Generation** | `llama3.2:3b` or `qwen2.5:3b` | \~2GB | Any small model works well for this. | | **Hindsight** | `llama3.2:3b` or `qwen2.5:7b` | \~2-4GB | Small models are fine; step up to 7B for richer memory. | | **Transcription** | `whisper:large-v3` | \~3GB | Standard Whisper model for speech-to-text. | These are starting points. The open-source model landscape evolves rapidly — check the [Ollama model library](https://ollama.com/library) for the latest options. ### Connecting Ollama to LiteLLM [Section titled “Connecting Ollama to LiteLLM”](#connecting-ollama-to-litellm) LiteLLM has native support for Ollama. Once Ollama is running, add it as a provider in your LiteLLM configuration and your locally hosted models will appear alongside any cloud models you have configured. Errand sees them all the same way. ## vLLM [Section titled “vLLM”](#vllm) [vLLM](https://vllm.ai/) is a high-performance inference engine designed for production deployments. It is more complex to set up than Ollama but delivers significantly better throughput, especially when serving multiple concurrent requests. ### When to Choose vLLM Over Ollama [Section titled “When to Choose vLLM Over Ollama”](#when-to-choose-vllm-over-ollama) * **Production deployments** where you need consistent performance under load * **GPU clusters** with multiple GPUs that you want to use efficiently * **Higher throughput** — vLLM’s PagedAttention engine is optimised for serving many requests * **Team environments** where multiple users or Errand instances share the same model server For a single user on a single machine, Ollama is simpler and works well. For anything larger, vLLM is worth the additional setup effort. ### Getting Started [Section titled “Getting Started”](#getting-started-1) vLLM can be installed via pip or run as a Docker container. See the [vLLM documentation](https://docs.vllm.ai/) for detailed setup instructions. ### Connecting vLLM to LiteLLM [Section titled “Connecting vLLM to LiteLLM”](#connecting-vllm-to-litellm) vLLM exposes an OpenAI-compatible API, so LiteLLM can connect to it directly. Add your vLLM endpoint as an OpenAI-compatible provider in LiteLLM and configure the models you are serving. ## Other Options [Section titled “Other Options”](#other-options) Several other tools can serve models locally. These are worth mentioning if you have specific needs: * **[llama.cpp](https://github.com/ggml-ai/llama.cpp)** — The low-level inference engine that powers Ollama under the hood. Use it directly if you want maximum control over quantisation, context sizes, and performance tuning. Command-line focused with no GUI. * **[LM Studio](https://lmstudio.ai/)** — A desktop application with a graphical interface for downloading and running models. Good for experimentation and trying out different models before committing to one. Exposes an OpenAI-compatible API that LiteLLM can connect to. * **[LocalAI](https://localai.io/)** — An OpenAI-compatible API wrapper that can serve multiple model types (language, image, audio). Useful if you want a single local server that handles all your AI needs. ## The Hybrid Approach [Section titled “The Hybrid Approach”](#the-hybrid-approach) For most users interested in local models, a hybrid setup delivers the best experience: run affordable local models for the simpler tasks, and use a cloud provider for the agent where quality matters most. ![Hybrid approach diagram showing the cloud provider handling the agent model while Ollama runs title generation, Hindsight, and Whisper models locally, all routed through LiteLLM](/_astro/hybrid-model-selection.ClF0L6el_JSMkt.webp) This gives you: * **Privacy where it matters.** Your voice recordings and memory data never leave your machine. * **Low cost for simple tasks.** Title generation and memory operations run locally at no per-token cost. * **High quality for the agent.** The agent — where capability matters most — uses a capable cloud model. * **Simplicity.** LiteLLM routes requests to the right backend automatically. Errand does not know or care which models are local and which are cloud-hosted. ## Configuration Tips [Section titled “Configuration Tips”](#configuration-tips) ### Increase the LLM Timeout [Section titled “Increase the LLM Timeout”](#increase-the-llm-timeout) Local models, especially larger ones, can take longer to load into memory and generate responses. The default LLM timeout of 30 seconds may not be enough. Go to **Settings > Task Management** and increase the **LLM Timeout** to at least 120 seconds for local models. If you see timeout errors, increase it further. See the [Task Management documentation](/docs/configuration/task-management/) for details. ### Quantisation [Section titled “Quantisation”](#quantisation) Most local model tools support **quantised** versions of models — smaller, faster files that trade a small amount of quality for significantly reduced memory requirements. For example, a 70B model in 4-bit quantisation needs roughly half the VRAM of the full-precision version. For Errand’s Efficient-tier tasks (title generation, Hindsight), quantised models work extremely well. For the agent model, use the least aggressive quantisation your hardware can handle to preserve tool-calling reliability. ### Model Loading Time [Section titled “Model Loading Time”](#model-loading-time) The first request to a local model may take significantly longer as the model loads into GPU memory. Subsequent requests are fast. If you notice long delays on the first task after starting your system, this is normal — the model is warming up. --- # LLM Providers > A guide to the cloud providers and services that offer AI models compatible with Errand. Errand works with any LLM provider that offers an OpenAI-compatible API — which, through [LiteLLM](/docs/ai-models/), means virtually all of them. This page surveys the major providers and services to help you decide where to get your models. All of the providers listed here connect to Errand through LiteLLM. You configure your provider credentials and models in LiteLLM once, and then select the models you want to use from within Errand’s settings. ## Cloud Providers [Section titled “Cloud Providers”](#cloud-providers) These are the companies that build and host their own AI models. You sign up for an account, get an API key, and pay per use. This is the simplest way to get started — no hardware required, and you get access to the most capable models available. ### Anthropic (Claude) [Section titled “Anthropic (Claude)”](#anthropic-claude) Anthropic builds the Claude family of models, which are known for strong reasoning, reliable tool use, and careful instruction following. Claude models are a popular choice for agentic workloads like Errand because of their consistency in multi-step tasks. | Tier | Model | Notes | | ------------- | ---------------- | ------------------------------------ | | **Frontier** | Claude Opus 4 | Best reasoning and tool use | | **Balanced** | Claude Sonnet 4 | Excellent all-rounder, great value | | **Efficient** | Claude Haiku 4.5 | Fast and affordable for simple tasks | **Strengths:** Reliable tool calling, strong instruction following, long context windows, thoughtful safety design. Sign up at [anthropic.com](https://www.anthropic.com/). ### OpenAI (GPT) [Section titled “OpenAI (GPT)”](#openai-gpt) OpenAI produces the GPT family of models, the most widely used commercial AI models. The ecosystem is mature, with extensive documentation and broad tool support. | Tier | Model | Notes | | ------------- | ----------- | ---------------------------- | | **Frontier** | GPT-4.1 | Latest flagship model | | **Balanced** | GPT-4o | Strong general-purpose model | | **Efficient** | GPT-4o Mini | Compact and cost-effective | OpenAI also provides the **Whisper** speech-to-text API, which is the standard for Errand’s transcription feature. **Strengths:** Mature ecosystem, extensive documentation, broad compatibility, Whisper API for transcription. Sign up at [platform.openai.com](https://platform.openai.com/). ### Google (Gemini) [Section titled “Google (Gemini)”](#google-gemini) Google’s Gemini models offer very large context windows and competitive performance, particularly in the Balanced and Efficient tiers. Google’s pricing is often attractive, especially for the Flash models. | Tier | Model | Notes | | ------------- | ---------------- | -------------------------------------- | | **Frontier** | Gemini 2.5 Pro | Large context window, strong reasoning | | **Balanced** | Gemini 2.5 Flash | Excellent performance-to-cost ratio | | **Efficient** | Gemini 2.0 Flash | Very fast, very affordable | **Strengths:** Large context windows, competitive pricing, strong performance in the Balanced tier. Sign up at [ai.google.dev](https://ai.google.dev/). ### xAI (Grok) [Section titled “xAI (Grok)”](#xai-grok) xAI’s Grok models are a newer entrant with strong reasoning capabilities. The Grok family has been rapidly improving and is worth considering, particularly if you are looking for alternatives to the established providers. | Tier | Model | Notes | | ------------ | ----------- | ------------------------------- | | **Frontier** | Grok 3 | Strong reasoning, large context | | **Balanced** | Grok 3 Mini | Compact, capable model | **Strengths:** Competitive reasoning performance, growing model lineup. Sign up at [console.x.ai](https://console.x.ai/). ### Other Providers [Section titled “Other Providers”](#other-providers) Several other providers offer capable models that work well with Errand through LiteLLM: * **Mistral** — European AI company offering strong open-weight models. Models like Mistral Large sit in the Balanced tier. A good choice if data residency in the EU matters to you. Sign up at [mistral.ai](https://mistral.ai/). * **DeepSeek** — Offers highly capable models at competitive price points. DeepSeek-R1 is known for strong reasoning. Worth considering for cost-conscious deployments. Sign up at [platform.deepseek.com](https://platform.deepseek.com/). * **Cohere** — Focuses on enterprise use cases with models designed for search, retrieval, and business applications. Sign up at [cohere.com](https://cohere.com/). LiteLLM supports over 100 providers. If your preferred provider is not listed here, check the [LiteLLM documentation](https://docs.litellm.ai/docs/providers) to see if it is supported. ## Aggregators and Gateways [Section titled “Aggregators and Gateways”](#aggregators-and-gateways) These services give you access to models from multiple providers through a single account. They sit between you (or rather, between LiteLLM) and the model providers, handling authentication and billing in one place. ### OpenRouter [Section titled “OpenRouter”](#openrouter) [OpenRouter](https://openrouter.ai/) provides access to models from Anthropic, OpenAI, Google, Meta, Mistral, and many others — all through a single API key. It is a good choice if you want to experiment with models from different providers without signing up for separate accounts with each one. OpenRouter also offers access to open-source and community models that might not be available directly from the original providers. **Best for:** Individuals and small teams who want flexibility and easy access to a wide range of models. ### AWS Bedrock [Section titled “AWS Bedrock”](#aws-bedrock) [Amazon Bedrock](https://aws.amazon.com/bedrock/) is Amazon’s managed AI service. It provides access to models from Anthropic (Claude), Meta (Llama), Mistral, and others, all within the AWS ecosystem. Your data stays within your AWS account and is covered by your existing AWS agreements. **Best for:** Teams and organisations already on AWS who need enterprise compliance, billing through their existing AWS account, or data residency guarantees. ### Azure OpenAI Service [Section titled “Azure OpenAI Service”](#azure-openai-service) [Azure OpenAI Service](https://azure.microsoft.com/en-us/products/ai-services/openai-service) provides access to OpenAI’s GPT models within the Microsoft Azure cloud. Like Bedrock, it is designed for enterprise deployments with existing cloud commitments. **Best for:** Teams and organisations already on Azure who need enterprise compliance and want to use GPT models through their existing Azure agreement. ### Google Cloud Vertex AI [Section titled “Google Cloud Vertex AI”](#google-cloud-vertex-ai) [Vertex AI](https://cloud.google.com/vertex-ai) is Google Cloud’s AI platform. It provides access to Gemini models and other Google AI capabilities within the GCP ecosystem. **Best for:** Teams and organisations already on Google Cloud who want to use Gemini models through their existing GCP account. ## Choosing a Provider [Section titled “Choosing a Provider”](#choosing-a-provider) There is no single “best” provider — the right choice depends on your situation: * **Getting started as an individual?** Sign up directly with one of the major cloud providers (Anthropic, OpenAI, or Google) and use their API key in LiteLLM. Alternatively, use OpenRouter for easy access to models from multiple providers with a single account. * **Working in a team or enterprise?** Use the cloud platform your organisation already has a relationship with. If you are on AWS, use Bedrock. On Azure, use Azure OpenAI. On GCP, use Vertex AI. This simplifies billing, compliance, and access management. * **Want to compare models?** Start with OpenRouter or set up multiple providers in LiteLLM. You can easily switch between models to find what works best for your tasks. * **Privacy or data residency concerns?** Consider a European provider like Mistral, a cloud platform with data residency options (Bedrock, Azure, Vertex), or [run models locally](/docs/ai-models/local-models/). Whichever provider you choose, the experience in Errand is the same — LiteLLM handles the translation between providers, so you can always change your mind later without reconfiguring Errand itself. --- # Errand Service The **worker** is the component that turns your tasks into action. When you create a task in Errand, the worker picks it up, spins up an isolated container to run it, streams logs back in real time, and collects the result. Everything happens automatically — you just watch the progress from the task board. ## How the Worker Fits In [Section titled “How the Worker Fits In”](#how-the-worker-fits-in) Errand has three main components: * **Server** — The API and web interface you interact with * **Worker** — The background process that executes tasks (this page) * **Task Runner** — A lightweight container image that runs inside the worker’s containers, providing the AI agent with tools and a sandboxed environment The worker runs as a separate process (or pod, in Kubernetes) alongside the server. It connects to the same database and message bus, but its only job is executing tasks. ## Task Lifecycle [Section titled “Task Lifecycle”](#task-lifecycle) When a task moves to the **Pending** column on your task board, the worker picks it up and carries it through a well-defined lifecycle. ![Worker task lifecycle diagram showing polling, preparation, runtime selection, container lifecycle, and output handling](/_astro/worker-lifecycle.BVuFDsfT_2mrI4z.webp) ### 1. Polling and Dequeue [Section titled “1. Polling and Dequeue”](#1-polling-and-dequeue) The worker continuously polls the database for pending tasks. When it finds one, it locks the row (using `SELECT ... FOR UPDATE SKIP LOCKED` so multiple workers don’t grab the same task) and begins processing. If no tasks are available, the worker sleeps briefly before checking again. ### 2. Preparation [Section titled “2. Preparation”](#2-preparation) Before launching a container, the worker gathers everything the task-runner will need: * **Settings** — The global configuration (AI model, system prompt, MCP servers, credentials) * **Task Profile** — If the task matches a [profile](/docs/docs/configuration/task-profiles/), the profile’s overrides are applied (different model, custom system prompt, restricted tools, etc.) * **Platform Credentials** — GitHub tokens, cloud storage OAuth tokens, and other integration credentials are loaded from the database * **Token Refresh** — Cloud storage tokens (Google Drive, OneDrive) are checked for expiry and refreshed if needed before being injected into the container Once preparation is complete, the task status changes to **Running** and a real-time update is pushed to the UI. ### 3. Container Runtime Selection [Section titled “3. Container Runtime Selection”](#3-container-runtime-selection) The worker supports three container runtimes, selected by the `CONTAINER_RUNTIME` environment variable: | Runtime | Value | Used By | How It Works | | -------------- | ------------ | --------------------------------- | ---------------------------------------------------------------------------------------- | | **Docker** | `docker` | Local development, Docker Compose | Creates containers via the Docker SDK inside a Docker-in-Docker sidecar | | **Kubernetes** | `kubernetes` | Production clusters | Creates Kubernetes Jobs with ConfigMaps for input and emptyDir volumes for output | | **Apple** | `apple` | Errand Desktop (macOS) | Delegates to the desktop app’s bridge API, which uses Apple’s Containerization framework | All three runtimes implement the same interface — `prepare()`, `run()`, `result()`, `cleanup()` — so the rest of the worker code doesn’t need to know which runtime is in use. ### 4. Building the Container Configuration [Section titled “4. Building the Container Configuration”](#4-building-the-container-configuration) The worker assembles three files that are injected into every task-runner container: * **`prompt.txt`** — The task description, exactly as you wrote it * **`system_prompt.txt`** — The system prompt, enriched with recalled memories from Hindsight, skill manifests, cloud storage instructions, and repo context discovery guidance * **`mcp.json`** — The MCP server configuration, defining which tools the agent can use The MCP configuration is built dynamically based on what’s available and what the task’s profile allows: * **Errand MCP** — Always injected (provides tools like `new_task`, `post_tweet`, `send_email`) * **Hindsight** — Injected if a Hindsight memory server is configured (provides `retain`, `recall`, `reflect`) * **Playwright** — Injected if the Playwright sidecar is healthy (provides browser automation) * **LiteLLM** — Injected if LiteLLM MCP servers are enabled (provides access to additional AI models) * **Cloud Storage** — Injected if the user has connected Google Drive or OneDrive and valid tokens exist * **User-configured servers** — Any custom MCP servers you’ve added in settings Environment variables (API keys, model selection, max turns, reasoning effort) and optional SSH credentials for Git access are also prepared at this stage. ### 5. Running the Task [Section titled “5. Running the Task”](#5-running-the-task) The container is created via `runtime.prepare()` and then started with `runtime.run()`. During execution: * **Log streaming** — Every log line from the task-runner is published to Valkey (Redis) in real time, which the server relays to your browser via Server-Sent Events. You see the agent’s reasoning, tool calls, and progress as it happens. * **Heartbeat updates** — The worker periodically updates a heartbeat timestamp in the database. If the worker crashes mid-task, this heartbeat allows another worker (or the same worker after restart) to detect orphaned tasks and recover them. * **Callback token refresh** — A one-time token stored in Valkey allows the task-runner to push its result back to the server. The token’s TTL is refreshed periodically for long-running tasks. ### 6. Collecting the Result [Section titled “6. Collecting the Result”](#6-collecting-the-result) When the container exits, the worker collects the result through two channels: 1. **Callback result** — The task-runner can push its structured JSON output directly to the server via an internal API endpoint. This is the preferred path because it doesn’t depend on parsing container logs. 2. **Container stdout** — As a fallback, the worker reads the container’s stdout and looks for a JSON object containing `status` and `result` fields. The structured output includes: * **`status`** — Either `completed` (task finished successfully) or `needs_input` (the agent has questions for you) * **`result`** — The agent’s response text * **`questions`** — Optional list of questions if the agent needs clarification ### 7. Output Handling [Section titled “7. Output Handling”](#7-output-handling) Based on the result, the task moves to one of three destinations: * **Completed** — Valid output with `status: "completed"`. The task moves to the Completed column. If it’s a repeating task, a clone is created for the next scheduled run. * **Review** — Valid output with `status: "needs_input"`. The task moves to the Review column with the agent’s questions displayed. You can provide answers and send it back for another round. * **Retry** — No valid structured output, or the container exited with an error. The task is moved back to Scheduled with exponential backoff (1 minute, 2 minutes, 4 minutes, etc.) and a “Retry” tag is added. After 5 failed attempts, the task moves to Review for manual inspection. ### 8. Cleanup [Section titled “8. Cleanup”](#8-cleanup) Regardless of the outcome, `runtime.cleanup()` always runs. This removes the container (Docker), deletes the Job and ConfigMap (Kubernetes), or calls the bridge API’s delete endpoint (Apple). In Docker mode, the Playwright sidecar container is also cleaned up. ## Orphan Recovery [Section titled “Orphan Recovery”](#orphan-recovery) If a worker crashes while a task is running, the task would be stuck in the “running” state forever. To handle this, when a worker starts up it scans for orphaned Kubernetes Jobs (or Docker containers) left behind by a previous instance: * If the associated task is still marked as “running” in the database and has retries remaining, it’s moved back to **Scheduled** with backoff * If retries are exhausted, it’s moved to **Review** with a note explaining what happened * The orphaned container resources are cleaned up This ensures no task is permanently lost, even if the infrastructure has issues. ## Scaling [Section titled “Scaling”](#scaling) In Kubernetes deployments, you can run multiple worker replicas. The `SKIP LOCKED` query ensures each worker picks up different tasks, so they naturally load-balance without coordination. Each worker independently manages its own containers and log streams. --- # Architecture Overview > How the components of the Errand ecosystem work together. Errand is built as a set of loosely-coupled components that work together to turn your natural language instructions into completed work. This page explains what each component does and how they interact. ![Errand architecture diagram showing the Browser UI, Errand Server, Worker, MCP Servers, Errand Cloud, Errand Desktop, and supporting services](/_astro/architecture.DbtcoWRV_Z10nmE3.webp) ## Components at a Glance [Section titled “Components at a Glance”](#components-at-a-glance) | Component | Role | | ------------------ | ------------------------------------------------------------------------------------------------------------- | | **Errand Server** | FastAPI application — serves the web UI, REST API, and coordinates everything | | **Worker** | Background process that picks up tasks and runs them in isolated containers | | **Task Runner** | Ephemeral container image that provides the AI agent with a sandboxed environment and tools | | **MCP Servers** | Tool servers (Model Context Protocol) that give agents access to email, web search, task management, and more | | **Valkey** | In-memory message bus for real-time log streaming and pub/sub events | | **PostgreSQL** | Persistent storage for tasks, settings, credentials, and user data | | **Errand Cloud** | Optional hosted service for secure remote access and webhook relay | | **Errand Desktop** | macOS application that manages the full installation using Apple Containerization | ## Errand Server [Section titled “Errand Server”](#errand-server) The server is the central hub. It runs as a single FastAPI application that handles multiple responsibilities: * **Web UI** — Serves the Vue 3 single-page application that you interact with in your browser. The frontend communicates with the server over REST and Server-Sent Events (SSE) for real-time updates. * **Task orchestration** — Manages the task lifecycle: receiving new tasks, assigning them to workers, tracking status, and delivering results back to the UI. * **Authentication** — Handles user login via Keycloak OIDC (single sign-on), issuing and validating JWT tokens. * **MCP endpoint** — Exposes a built-in [MCP server](/docs/mcp-server/) at `/mcp/` that agents (and external tools) use to interact with Errand’s capabilities. * **Integration APIs** — OAuth flows for cloud storage, webhook endpoints for Slack, and credential management for all connected platforms. The server does not execute tasks itself — it delegates that to the worker. ## Worker and Task Runner [Section titled “Worker and Task Runner”](#worker-and-task-runner) The **worker** is a separate process that runs the same codebase as the server but with a different entrypoint. Its job is straightforward: poll the database for pending tasks, launch a container for each one, stream logs back in real time, and collect the result. For each task, the worker spins up an ephemeral **task runner** container. This is a lightweight image containing an AI agent (powered by the configured LLM) and a set of tools available via MCP. The container receives: * A prompt file with your task description * A system prompt with instructions, recalled memories, and skill definitions * An MCP configuration file defining which tool servers the agent can use * Environment variables for API keys, model selection, and other settings The task runner executes the agent loop — reasoning, calling tools, and producing a structured result — then exits. The worker collects the output and updates the task status. The container is destroyed immediately after, leaving no persistent state behind. This isolation means each task starts clean, with no risk of one task’s data leaking into another. For a detailed walkthrough of the task lifecycle, see the [Worker Process](/docs/architecture/workers/) page. ### Container Runtimes [Section titled “Container Runtimes”](#container-runtimes) The worker supports three container runtimes, selected by environment configuration: * **Docker** — Used for local development and Docker Compose deployments. Containers run inside a Docker-in-Docker sidecar. * **Kubernetes** — Used for production clusters. Each task becomes a Kubernetes Job with its own Pod, ConfigMap, and volumes. * **Apple Containerization** — Used by Errand Desktop on macOS. The worker delegates container management to the desktop app via a local bridge API, which uses Apple’s native virtualization framework. All three runtimes implement the same interface, so the rest of the system doesn’t need to know which one is in use. ## LLM Integration [Section titled “LLM Integration”](#llm-integration) Errand doesn’t bundle its own AI model. Instead, it connects to an external LLM endpoint using the OpenAI-compatible API format. This gives you flexibility in choosing which model to use and where it runs. See the [AI Models](/docs/ai-models/) guide for help choosing the right models and providers. A common setup is to use [LiteLLM](https://docs.litellm.ai/) as a proxy in front of one or more model providers. LiteLLM presents a unified OpenAI-compatible API and lets you route requests to different backends — OpenAI, Anthropic, local models via Ollama, or any other provider — without changing your Errand configuration. You just set the `OPENAI_BASE_URL` to point at your LiteLLM instance and configure the model name in Errand’s settings. The worker injects the LLM endpoint and API key into every task runner container, so agents always know where to send their requests. If LiteLLM is configured with MCP server support, Errand can also inject a **LiteLLM MCP gateway** into the agent’s tool configuration, giving the agent access to additional tools hosted behind LiteLLM. ## MCP Servers [Section titled “MCP Servers”](#mcp-servers) [MCP (Model Context Protocol)](/docs/mcp-server/) is an open standard for connecting AI agents to tools. Errand uses MCP extensively — both as a provider and a consumer of tools. ### Built-in MCP Server [Section titled “Built-in MCP Server”](#built-in-mcp-server) Errand’s server exposes an MCP endpoint at `/mcp/` that provides tools for: * Creating and managing tasks (`new_task`, `task_status`, `list_tasks`) * Sending and reading emails * Searching the web * Posting to social media This server is automatically injected into every task runner, so agents can always interact with Errand itself. But it’s not limited to internal use — any MCP-compatible client on your network can connect to it. ### External MCP Clients [Section titled “External MCP Clients”](#external-mcp-clients) Because Errand’s MCP server uses the standard protocol, you can point other AI tools at it. For example: * **Claude Code** or **Cursor** can use Errand’s MCP server to create tasks, check status, or trigger workflows from within your IDE * **Custom agents** built with the Anthropic Agent SDK or OpenAI Agents SDK can manage Errand tasks programmatically * **Other MCP-compatible applications** can integrate with Errand without any custom API work This turns Errand into a task execution backend that any AI agent can use, not just the agents running inside Errand’s own containers. ### Injected MCP Servers [Section titled “Injected MCP Servers”](#injected-mcp-servers) When the worker prepares a task runner container, it dynamically builds the MCP configuration based on what’s available and what the task’s [profile](/docs/configuration/task-profiles/) allows. Servers that may be injected include: * **Errand** — Task management and integrations (always available) * **Hindsight** — Persistent memory (if configured) * **Playwright** — Browser automation (if the Playwright sidecar is healthy) * **LiteLLM** — Additional AI model tools (if enabled) * **Google Drive / OneDrive** — Cloud file access (if the user has connected their account) * **User-configured servers** — Any custom MCP servers added in settings ## AI Memory with Hindsight [Section titled “AI Memory with Hindsight”](#ai-memory-with-hindsight) AI agents forget everything between tasks. Without memory, every task starts from zero — no context about your preferences, past decisions, or what the agent learned last time. Errand integrates with [Hindsight](https://hindsight.vectorize.io/) to solve this. Before each task runs, the worker queries Hindsight with the task description and injects any relevant memories into the system prompt. The agent also has direct access to Hindsight’s MCP tools (`retain`, `recall`, `reflect`) so it can store new memories during execution and search for additional context when needed. This means knowledge accumulates over time. An agent that researched a topic last week can build on that work today, without you having to repeat the context. ## Valkey (Message Bus) [Section titled “Valkey (Message Bus)”](#valkey-message-bus) Valkey (a Redis-compatible in-memory store) serves as the real-time communication layer: * **Log streaming** — As a task runner produces output, the worker publishes each log line to a Valkey channel. The server subscribes to these channels and forwards events to the browser via SSE, so you see the agent’s reasoning in real time. * **Event pub/sub** — Task status changes, new tasks, and other events are broadcast through Valkey so that all connected clients stay in sync. * **OAuth state** — Short-lived tokens for OAuth flows (cloud storage connections) are stored in Valkey with a TTL. * **Callback tokens** — One-time tokens that allow task runners to push results back to the server are stored and refreshed in Valkey. ## PostgreSQL [Section titled “PostgreSQL”](#postgresql) All persistent data lives in PostgreSQL: * Tasks (status, output, logs, retry count, scheduling) * User settings and preferences * Platform credentials (encrypted with Fernet symmetric encryption) * Tags, profiles, and skill definitions The server and worker share the same database. Alembic manages schema migrations. ## Errand Cloud [Section titled “Errand Cloud”](#errand-cloud) By default, Errand only runs on your local network. The **Errand Cloud** service is an optional subscription that provides two things: ### Secure Remote Access [Section titled “Secure Remote Access”](#secure-remote-access) Your Errand installation maintains a persistent encrypted connection to the cloud service. When you visit [errand.cloud](https://errand.cloud) from anywhere in the world, your requests are proxied through this connection to your local server. Your data never sits on the cloud — it only passes through. ### Webhook Relay [Section titled “Webhook Relay”](#webhook-relay) Services like [Slack](/docs/integrations/slack/) need a public URL to send events to. Since your home server doesn’t have one, Errand Cloud receives those webhooks and forwards them to your installation. This is what makes it possible to create tasks from Slack, receive real-time updates, and interact with Errand from anywhere — without exposing your server directly to the internet. If your installation goes offline, webhooks are queued for up to 48 hours until it comes back. ## Errand Desktop [Section titled “Errand Desktop”](#errand-desktop) For macOS users, **Errand Desktop** is a native Swift application that manages the entire Errand installation on your Mac. It handles downloading container images, configuring the server and worker, setting up Hindsight, and managing the container runtime using Apple’s Containerization framework. Errand Desktop sets `CONTAINER_RUNTIME=apple` on the worker, which tells it to delegate container management to the desktop app’s bridge API rather than using Docker or Kubernetes. This provides a seamless experience — you launch one app and everything just works. ## How It All Fits Together [Section titled “How It All Fits Together”](#how-it-all-fits-together) A typical flow looks like this: 1. You type a task description in the **Browser UI** (or send it from **Slack**, or create it via the **MCP server** from your IDE) 2. The **Errand Server** saves the task to **PostgreSQL** and broadcasts a new-task event via **Valkey** 3. The **Worker** picks up the task, loads settings and credentials, refreshes any expired OAuth tokens, and prepares the container configuration 4. The worker launches an ephemeral **Task Runner** container via the configured runtime (Docker, Kubernetes, or Apple) 5. The task runner’s AI agent calls the **LLM endpoint** for reasoning and uses **MCP Servers** for tools — searching the web, reading emails, accessing files, querying **Hindsight** for memory 6. Log lines stream back through **Valkey** to the **Server** to your **Browser** in real time 7. When the agent finishes, the worker collects the structured result, updates the task in **PostgreSQL**, and destroys the container 8. If you’re accessing Errand remotely, all of this flows transparently through **Errand Cloud** --- # Errand Cloud > Secure remote access, webhook relay, and cloud authentication for your Errand installation. Errand is designed to run on your own hardware — your home server, personal computer, or any device you control. By default, it’s only accessible from your local network. That’s great for privacy, but what if you need to manage a task while you’re away from home? Or connect to services like Slack and GitHub that need to reach your server? That’s where **Errand Cloud** comes in. ## What is Errand Cloud? [Section titled “What is Errand Cloud?”](#what-is-errand-cloud) Errand Cloud is an optional service that gives your local Errand installation superpowers without compromising your privacy. It provides three core capabilities: * **[Remote access](/docs/cloud-service/remote-management/)** — Manage your tasks from anywhere via , with a mobile-friendly interface that works on phones and tablets * **[Webhook relay](/docs/cloud-service/webhook-relays/)** — Services like Slack, Jira, and GitHub need a public URL to send events to. Since your home server doesn’t have one, Errand Cloud receives those webhooks and forwards them to your installation * **[Cloud authentication](/docs/cloud-service/cloud-authentication/)** — For integrations with Google Workspace and Microsoft 365, Errand Cloud acts as a secure OAuth proxy to handle authentication flows that aren’t possible on a local server All communication between your installation and the cloud service is encrypted. Your data never sits on the cloud service — it only passes through. All your task data stays on your local installation. ## How It Works [Section titled “How It Works”](#how-it-works) The connection between your local Errand installation and Errand Cloud is straightforward: 1. Your Errand installation maintains a **persistent encrypted connection** to the cloud service 2. When you access [errand.cloud](https://errand.cloud), your requests are **relayed through this connection** to your local server 3. Webhooks from services like Slack are **received by the cloud and forwarded** to your installation 4. If your installation goes offline, webhooks are **queued for up to 48 hours** until it comes back online ## Setting Up Errand Cloud [Section titled “Setting Up Errand Cloud”](#setting-up-errand-cloud) Getting connected takes just a few minutes. ### Step 1: Create an Account [Section titled “Step 1: Create an Account”](#step-1-create-an-account) Visit and create your account. ### Step 2: Subscribe to a Plan [Section titled “Step 2: Subscribe to a Plan”](#step-2-subscribe-to-a-plan) All new users receive a free trial period. Before that trial period expires, you should choose a monthly or annual subscription plan that works for you. ### Step 3: Open Cloud Settings in Errand [Section titled “Step 3: Open Cloud Settings in Errand”](#step-3-open-cloud-settings-in-errand) In your Errand installation, go to **Settings > Cloud Service**. ### Step 4: Connect Your Installation [Section titled “Step 4: Connect Your Installation”](#step-4-connect-your-installation) Click the **“Connect”** button and sign in with your Errand Cloud account. ### Step 5: Confirm the Connection [Section titled “Step 5: Confirm the Connection”](#step-5-confirm-the-connection) Once connected, you’ll see your subscription status and cloud endpoints on the settings page. ![Cloud Service settings page](/_astro/settings-cloud.Bu3CC93M_2rgbX0.webp) ## Managing Your Account [Section titled “Managing Your Account”](#managing-your-account) From the Cloud Service settings page, you can: * Click **“Manage Account”** to access subscription management, update payment details, or change your plan * Click **“Disconnect”** to unlink your installation from Errand Cloud ## Privacy and Data [Section titled “Privacy and Data”](#privacy-and-data) The cloud service **never stores your task data**. It only relays requests between your browser (or webhook senders) and your local installation. All your tasks, emails, configurations, and other data remain entirely on your own hardware. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) **Not connecting to the cloud service?** * Check that your Errand server has an active internet connection * Make sure your firewall isn’t blocking outbound connections from Errand * Try disconnecting and reconnecting from the Cloud Service settings page **Subscription expired?** * Visit **“Manage Account”** from the Cloud Service settings page to renew your subscription * Remote access and webhook relay will stop working until your subscription is active again --- # Cloud Service Authentication > Use Errand Cloud to authenticate with Google Workspace, Microsoft 365, and other cloud services. Some integrations — like Google Drive and OneDrive — require an **OAuth authentication flow** that involves redirecting your browser to the service provider, signing in, and being redirected back to a callback URL. This flow requires a publicly accessible URL, which your local Errand installation doesn’t have. Errand Cloud solves this by acting as a **secure OAuth proxy** for these authentication flows. ## How Cloud Authentication Works [Section titled “How Cloud Authentication Works”](#how-cloud-authentication-works) When you connect a cloud service like Google Drive or OneDrive through Errand Cloud: 1. You click **Connect** on the integration card in your Errand settings 2. Your browser is redirected to the service provider’s sign-in page (Google, Microsoft, etc.) 3. After you grant permission, the provider redirects to an **Errand Cloud callback URL** 4. Errand Cloud relays the authentication tokens back to your local installation through the encrypted connection 5. Your local Errand server stores the tokens and uses them for API access After the initial authentication, your installation communicates directly with the cloud service APIs using the stored tokens. Errand Cloud is only involved during the OAuth sign-in flow — it does not see or store your files, emails, or other data from these services. ## Supported Services [Section titled “Supported Services”](#supported-services) ### Google Workspace [Section titled “Google Workspace”](#google-workspace) Errand Cloud can proxy OAuth flows for Google services, enabling integrations such as: * **[Google Drive](/docs/integrations/google-drive/)** — give task-runner agents read/write access to files in your Google Drive Each Google integration requires its own OAuth consent and permissions. See the individual integration guides for setup instructions. ### Microsoft 365 [Section titled “Microsoft 365”](#microsoft-365) Errand Cloud can proxy OAuth flows for Microsoft services, enabling integrations such as: * **[OneDrive](/docs/integrations/one-drive/)** — give task-runner agents read/write access to files in your OneDrive Each Microsoft integration requires its own app registration and consent. See the individual integration guides for setup instructions. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) To use cloud authentication: * Your Errand installation must be **connected to Errand Cloud** (see [Setting Up Errand Cloud](/docs/cloud-service/)) * You must have an **active Errand Cloud subscription** ## Security [Section titled “Security”](#security) * Errand Cloud only handles the OAuth redirect flow — it relays the authorisation code to your local installation * Your access tokens and refresh tokens are stored **only on your local installation** * Errand Cloud never has access to your files, emails, or other data from connected services * You can revoke access at any time from both the Errand settings and the service provider’s permissions page ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) **“Provider not configured” error?** * The OAuth client credentials (client ID, client secret) are not set in your Errand server’s environment. Check the integration guide for the required environment variables. **Redirect fails or shows an error?** * Ensure the redirect URI configured in your OAuth app matches the Errand Cloud callback URL exactly * Check that your Errand Cloud connection is active **Token refresh fails?** * The user may have revoked access from the service provider’s side — disconnect and reconnect the integration * For Microsoft integrations, check that the client secret hasn’t expired --- # Remote Task Management > Manage your Errand tasks from anywhere using Errand Cloud. Errand Cloud gives you **secure remote access** to your local Errand installation from anywhere in the world. Whether you’re at work, travelling, or just away from your home network, you can create, monitor, and manage tasks as if you were sitting in front of your server. ## How Remote Access Works [Section titled “How Remote Access Works”](#how-remote-access-works) When you connect your Errand installation to Errand Cloud, it establishes a **persistent encrypted connection** to the cloud service. This connection stays open in the background and allows the cloud service to relay requests between your browser and your local server. When you visit [errand.cloud](https://errand.cloud) and log in: 1. Your browser connects to the Errand Cloud service 2. Errand Cloud identifies your linked installation 3. Your requests are relayed through the encrypted connection to your local server 4. Your server processes the request and sends the response back through the same connection This means you get the **full Errand experience** remotely — the same interface, the same features, the same data. Nothing is stored on the cloud; it’s simply a secure tunnel to your local installation. ## What You Can Do Remotely [Section titled “What You Can Do Remotely”](#what-you-can-do-remotely) Everything you can do locally, you can do through Errand Cloud: * **Create new tasks** — type or dictate tasks from your phone * **Monitor running tasks** — watch progress and read agent logs in real time * **Review completed work** — check results, approve outputs, or retry tasks * **Manage your board** — organise, prioritise, and schedule tasks * **Update settings** — change configuration without being on your home network ## Mobile-Friendly Interface [Section titled “Mobile-Friendly Interface”](#mobile-friendly-interface) The Errand Cloud interface is optimised for mobile devices. The responsive design works well on phones and tablets, making it easy to manage tasks on the go. Common actions like creating a task or checking status are designed to be quick and accessible from a small screen. ## Offline Handling [Section titled “Offline Handling”](#offline-handling) If your local Errand installation goes offline (for example, if your home server restarts or loses its internet connection): * **Remote access pauses** — you’ll see a notification that your installation is offline * **Webhooks are queued** — incoming webhooks from Slack, GitHub, and other services are stored for up to 48 hours * **Automatic reconnection** — when your installation comes back online, it reconnects automatically and queued webhooks are delivered You don’t need to do anything to re-establish the connection. Errand handles reconnection in the background. ## Security [Section titled “Security”](#security) * All data in transit is encrypted using TLS * Your Errand Cloud account credentials are separate from your local Errand credentials * The cloud service never stores your task data, emails, files, or any other content * Sessions can be managed from the Cloud Service settings page --- # Webhook Relays > How Errand Cloud relays webhooks from Jira, GitHub, Slack, and other services to your local installation. Many external services — including Slack, GitHub, and Jira — communicate with your applications by sending **webhooks**: HTTP requests to a public URL whenever something happens (a message is sent, a pull request is opened, an issue is updated). Since your Errand installation runs on your local network and doesn’t have a public URL, these webhooks can’t reach it directly. Errand Cloud solves this by acting as a **webhook relay**. It provides public URLs that external services can send webhooks to, and forwards those requests to your local Errand installation through the encrypted connection. ## How Webhook Relay Works [Section titled “How Webhook Relay Works”](#how-webhook-relay-works) 1. When you connect to Errand Cloud, it generates **unique webhook URLs** for your installation 2. You configure your external services (Slack, GitHub, Jira) to send webhooks to these URLs 3. When a webhook arrives at Errand Cloud, it’s **immediately forwarded** to your local installation through the encrypted tunnel 4. Your local Errand server processes the webhook and takes the appropriate action If your installation is temporarily offline, webhooks are **queued for up to 48 hours** and delivered as soon as it comes back online. ## Cloud Endpoints [Section titled “Cloud Endpoints”](#cloud-endpoints) After connecting to Errand Cloud, you’ll find your webhook URLs on the **Settings > Cloud Service** page. These are the URLs you’ll use when configuring external services. ### Slack [Section titled “Slack”](#slack) Slack requires three separate webhook URLs: * **Events URL** — receives messages and other workspace events * **Commands URL** — handles slash commands like `/errand` * **Interactivity URL** — processes button clicks, menu selections, and other interactive components Copy these URLs into your Slack app configuration under **Event Subscriptions**, **Slash Commands**, and **Interactivity & Shortcuts** respectively. See the [Slack integration guide](/docs/integrations/slack/) for detailed setup instructions. ### GitHub [Section titled “GitHub”](#github) GitHub uses a single webhook URL for all events. When setting up a webhook on your repository or organisation: * **Payload URL** — use your Errand Cloud GitHub webhook endpoint * **Content type** — select `application/json` * **Events** — choose which events to send (or select “Send me everything”) See the [GitHub integration guide](/docs/integrations/github/) for detailed setup instructions. ### Jira [Section titled “Jira”](#jira) Jira Cloud uses a webhook URL to notify Errand when issues are created or updated. When configuring your Jira webhook: * **URL** — use your Errand Cloud Jira webhook endpoint * **Events** — select the issue events you want to trigger tasks See the [Jira integration guide](/docs/integrations/jira/) for detailed setup instructions. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) **Webhooks not arriving?** * Verify that the cloud endpoint URLs are correctly configured in your Slack app, GitHub webhook, or Jira settings * Check that your installation is online and connected to the cloud service (the settings page will show the connection status) * Confirm your Errand Cloud subscription is active **Delayed webhooks?** * If your installation was recently offline, queued webhooks may take a moment to be delivered after reconnection * Check your server logs for any processing errors **Webhook URL changed?** * Your webhook URLs remain stable as long as your installation stays connected to the same Errand Cloud account. If you disconnect and reconnect, new URLs may be generated — update your external service configurations if this happens. --- # Configuration Settings > Overview of Errand AI configuration and settings. Errand AI is highly configurable, letting you tailor the system to fit your workflow. All settings are managed from the **Settings** page, which you can access from the navigation bar in the Errand UI. ![Agent Configuration settings page](/_astro/settings-agent.BpA7Aqen_ZCgmVg.webp) ## Settings Sections [Section titled “Settings Sections”](#settings-sections) The Settings page has a sidebar on the left with the following sections. Click any section to jump to its settings: * **[Agent Configuration](/docs/docs/configuration/agent-config/)** — Customize the AI agent’s behavior, system prompt, skills, and tool servers. * **[Agent Skills](/docs/docs/configuration/agentskills/)** — Give your agent specialized abilities using portable skill packages with automatic dependency installation. * **[Task Management](/docs/docs/configuration/task-management/)** — Choose your LLM models, set timeouts, configure scheduling, and control log levels. * **[Security](/docs/docs/configuration/security/)** — Manage API keys and security-related settings. * **[Task Profiles](/docs/docs/configuration/task-profiles/)** — Create specialized profiles that change how the AI handles different types of tasks. * **[Integrations](/docs/docs/integrations/github/)** — Connect Errand to external services like GitHub, Slack, email, and more. * **[Cloud Service](/docs/docs/cloud-service/)** — Secure remote access, webhook relay, and cloud authentication for your installation. * **[User Management](/docs/docs/configuration/user-management/)** — Set up authentication, manage users, and configure single sign-on. ## How Settings Work [Section titled “How Settings Work”](#how-settings-work) Errand uses a layered settings system. When determining the value of a setting, the system checks in this order: 1. **Environment variables** — These have the highest priority. If a setting is defined as an environment variable (for example, in your Docker Compose file or Kubernetes manifest), it will always be used. 2. **Database settings** — Values you have saved through the Settings UI are stored in the database and used if no environment variable is set. 3. **Defaults** — If neither an environment variable nor a database value exists, Errand falls back to a built-in default. ### Read-Only Settings [Section titled “Read-Only Settings”](#read-only-settings) If a setting has been configured via an environment variable, it will appear as **read-only** in the UI. You will still be able to see its current value, but you will need to update the environment variable directly to change it. ### Sensitive Values [Section titled “Sensitive Values”](#sensitive-values) Settings that contain sensitive information, such as API keys and secrets, are automatically **masked** in the UI for security. The actual values are stored securely and used by the system, but they are never displayed in full. ### When Do Changes Take Effect? [Section titled “When Do Changes Take Effect?”](#when-do-changes-take-effect) Most settings take effect **immediately** after you click Save. However, some settings — particularly those related to worker processes or background services — may require a **worker restart** before the new values are picked up. The UI will indicate when a restart is needed. --- # Agent Configuration > Configure the AI agent's behavior, skills, and tools. The Agent Configuration page lets you control how the AI agent behaves when it works on your tasks. You can find it under **Settings > Agent Configuration**. ![Agent Configuration settings page](/_astro/settings-agent.BpA7Aqen_ZCgmVg.webp) ## System Prompt [Section titled “System Prompt”](#system-prompt) The **System Prompt** is a set of instructions that the AI agent follows for every task it handles. Think of it as the agent’s “personality” and “job description” combined. You can customize the system prompt to: * Change the agent’s tone or writing style. * Tell the agent to focus on specific topics or domains. * Add guidelines about how the agent should approach problems. * Include any standing instructions you want the agent to always follow. To update the system prompt, edit the text in the System Prompt box and click **Save**. ## Skills [Section titled “Skills”](#skills) Skills are portable packages that give the agent specialized abilities. Each skill follows the [Agent Skills](/docs/configuration/agentskills/) standard and includes a `SKILL.md` manifest file that describes what the skill does and how to use it. To add a skill manually: 1. Click the **Add Skill** button. 2. Fill in the skill details, including its name and the path to its directory. 3. Click Save. ### Skills Repository [Section titled “Skills Repository”](#skills-repository) If your team maintains a shared library of skills in a Git repository, you can sync them automatically. This is a great way to keep all your agents up to date with the latest skill definitions. To configure a skills repository: 1. Enter the **Repository URL** in SSH format (for example, `git@github.com:org/agent-skills.git`). 2. Set the **Branch** to pull from (for example, `main`). 3. Specify the **Skills Path** — the folder within the repository where your skill definitions live. 4. Click **Save** to sync the skills. Errand will pull the skills from the repository and make them available to your agents. ## MCP Server Configuration [Section titled “MCP Server Configuration”](#mcp-server-configuration) The **MCP Server Configuration** section (click to expand) lets you register additional [Model Context Protocol](https://modelcontextprotocol.io/) servers. MCP servers extend your agent’s capabilities by providing custom tools that the agent can use during task execution. For example, you might register an MCP server that gives the agent access to your company’s internal database, a proprietary API, or a specialized search tool. To add an MCP server: 1. Expand the MCP Server Configuration section. 2. Enter the server details, including its name and connection information. 3. Click Save. Once registered, MCP servers are available for agents to use across all tasks — or you can restrict them to specific [Task Profiles](/docs/docs/configuration/task-profiles/) for more fine-grained control. --- # Agent Skills > Give your agent specialized abilities using portable skill packages. Agent Skills are portable packages that give your agent specialized abilities — from generating images and analyzing data to interacting with third-party APIs. Each skill follows the open [Agent Skills](https://agentskills.io) standard and includes a `SKILL.md` manifest that describes what the skill does, when to use it, and how to invoke it. Errand supports two ways to provide skills to the agent: **built-in skills** that you create directly in the UI, and **Git repository skills** that are synced from a shared repository. ## How Skills Work [Section titled “How Skills Work”](#how-skills-work) When a task runs, Errand injects the selected skills into the agent’s working environment at `/workspace/skills/`. The agent receives a manifest listing all available skills and is instructed to read a skill’s `SKILL.md` before using it. Each skill directory can contain: * `SKILL.md` — The manifest with frontmatter (name, description) and full instructions. * `scripts/` — Executable scripts the agent can run (Python, Node, shell, etc.). * `references/` — Reference materials the agent can read for context. * `assets/` — Static files the skill needs (templates, images, data files). * `requirements.txt` — Python package dependencies (installed automatically). * `package.json` — Node package dependencies (installed automatically). ## Built-In Skills [Section titled “Built-In Skills”](#built-in-skills) Built-in skills are created and managed directly in the Errand UI. This is the simplest way to get started. To create a skill: 1. Go to **Settings > Agent Configuration**. 2. Scroll to the **Skills** section and click **Add Skill**. 3. Enter a **name** and **description** for the skill. 4. Write the skill instructions in the **Instructions** field (this becomes the body of `SKILL.md`). 5. Optionally attach files — for example, a Python script at `scripts/generate.py` or a `requirements.txt` for dependencies. 6. Click **Save**. Built-in skills are stored in Errand’s database and are available immediately. You can edit or remove them at any time from the Settings page. ### Example: A Simple Web Research Skill [Section titled “Example: A Simple Web Research Skill”](#example-a-simple-web-research-skill) A basic skill might not need any dependencies at all. Here is an example of a skill that instructs the agent to perform structured web research: **Name:** `web-research` **Description:** `Perform structured web research with source citations` **Instructions:** ```markdown ## Web Research When asked to research a topic: 1. Use the `web_search` tool to find relevant sources. 2. Read the top 3-5 results using `read_url`. 3. Synthesize the findings into a clear summary. 4. Include source URLs as citations. Always verify claims across multiple sources before including them. ``` This skill has no scripts or dependencies — it simply provides instructions that guide the agent’s behavior. ## Git Repository Skills [Section titled “Git Repository Skills”](#git-repository-skills) For teams that maintain a shared library of skills, Errand can sync skills from a Git repository. This keeps all your agents up to date with the latest skill definitions and makes it easy to version-control your skills alongside your other code. To configure a skills repository: 1. Go to **Settings > Agent Configuration**. 2. In the **Skills Repository** section, enter the **Repository URL** in SSH format (for example, `git@github.com:your-org/agent-skills.git`). 3. Set the **Branch** to pull from (for example, `main`). 4. Specify the **Skills Path** — the folder within the repository where your skill directories live (for example, `skills/`). 5. Click **Save**. Errand pulls the repository at task execution time, parses each skill directory, and makes them available to the agent. If a built-in skill and a Git skill have the same name, the built-in skill takes priority. ### Repository Structure [Section titled “Repository Structure”](#repository-structure) A typical skills repository looks like this: ```plaintext agent-skills/ skills/ web-research/ SKILL.md image-generator/ SKILL.md requirements.txt scripts/ generate.py batch_generate.py references/ prompts.md data-analyzer/ SKILL.md package.json scripts/ analyze.js ``` Each subdirectory under the skills path is treated as a separate skill. The directory name becomes the skill name if no `name` field is specified in the `SKILL.md` frontmatter. For a curated collection of ready-to-use skills, see the [Agent Skills](https://agentskills.io) community repository. ## Skill Dependencies [Section titled “Skill Dependencies”](#skill-dependencies) Many skills include scripts that require Python or Node packages not already present in the agent runtime environment. For example, an image generation skill might use the `google-genai` and `pillow` Python packages, or a data processing skill might rely on the `lodash` Node library. Errand handles this automatically. When a skill includes a `requirements.txt` or `package.json` file in its root directory, the agent runtime installs the declared dependencies at startup — before the agent begins executing the task. ### Python Dependencies [Section titled “Python Dependencies”](#python-dependencies) To declare Python dependencies, add a `requirements.txt` file to the skill’s root directory. This file uses standard [pip requirements format](https://pip.pypa.io/en/stable/reference/requirements-file-format/): requirements.txt ```plaintext google-genai pillow ``` When the agent runtime starts and finds this file, it installs the packages before handing control to the agent. The agent can then import and use them normally: scripts/generate.py ```python from google import genai from PIL import Image client = genai.Client() response = client.models.generate_images( model="gemini-3-pro-image-preview", prompt="a friendly robot mascot", ) ``` ### Node Dependencies [Section titled “Node Dependencies”](#node-dependencies) To declare Node dependencies, add a `package.json` file to the skill’s root directory: ```json { "dependencies": { "lodash": "^4.17.21", "csv-parse": "^5.5.0" } } ``` The runtime installs these packages and makes them available via `NODE_PATH`, so the agent’s scripts can require them directly: scripts/analyze.js ```javascript const _ = require('lodash'); const { parse } = require('csv-parse/sync'); // Process data... ``` ### Multiple Skills with Dependencies [Section titled “Multiple Skills with Dependencies”](#multiple-skills-with-dependencies) If several skills declare dependencies, they are all installed together. Python dependencies from multiple `requirements.txt` files are installed into the same target directory. Node dependencies from multiple `package.json` files are merged into a single manifest before installation. Note Dependency installation adds a small amount of time to task startup (typically 10-30 seconds depending on the packages). Tasks that do not use skills with dependencies are unaffected — the startup check is a fast no-op. You can use [Task Profiles](/docs/docs/configuration/task-profiles/) to control which skills are available for different types of tasks, keeping lightweight profiles fast. ### Security Model [Section titled “Security Model”](#security-model) Errand takes a deliberate approach to dependency security. Package managers (`pip`, `npm`) are used during the startup phase to install declared dependencies, and are then **completely removed** before the agent gains control. This means: * The agent **cannot** install additional packages at runtime. * Only dependencies explicitly declared in a skill’s `requirements.txt` or `package.json` are installed. * You control what gets installed by choosing which skills to make available. This design keeps the agent runtime minimal and secure while still supporting skills that need additional libraries. Dependency Trust When you add a skill — whether built-in or from a Git repository — you are trusting its declared dependencies. Review a skill’s `requirements.txt` or `package.json` before making it available, just as you would review any third-party code before running it. ### Limitations [Section titled “Limitations”](#limitations) * **System-level packages** (installed via `apt` or `apk`) are not supported. Skills must use Python wheels or pre-built Node packages that do not require system libraries beyond what the runtime image provides. Most popular packages (including Pillow, numpy, and pandas) ship self-contained wheels that work out of the box. * **Version conflicts** between skills are resolved by the package manager. If two skills declare conflicting versions of the same package, only one version will be installed. Use [Task Profiles](/docs/docs/configuration/task-profiles/) to isolate conflicting skills into separate profiles if needed. ## Controlling Skill Access with Profiles [Section titled “Controlling Skill Access with Profiles”](#controlling-skill-access-with-profiles) Not every task needs every skill. [Task Profiles](/docs/docs/configuration/task-profiles/) let you choose which skills are available for different types of work. For example: * A **Creative** profile might include an image generation skill with heavyweight dependencies. * A **Quick Reply** profile might exclude all skills for the fastest possible startup. * A **Research** profile might include web research and data analysis skills but not image generation. This keeps task startup fast for simple work while still supporting complex skills when you need them. ## The SKILL.md Format [Section titled “The SKILL.md Format”](#the-skillmd-format) Every skill must include a `SKILL.md` file. This file uses YAML frontmatter followed by Markdown instructions: ````markdown --- name: image-generator description: Generate images using Google Gemini --- ## Image Generation Generate images from text descriptions using Google's Gemini model. ### Prerequisites - `GEMINI_API_KEY` environment variable must be set. ### Usage Generate an image: ```bash python3 /scripts/generate.py "a sunset over mountains" -o sunset.png ```` ```plaintext The `name` and `description` fields appear in the agent's skill manifest. The body contains the full instructions that the agent reads when it decides to use the skill. For the complete specification and more examples, visit [agentskills.io](https://agentskills.io). ``` --- # Task Management > Configure task processing, LLM models, and scheduling options. The Task Management page controls how tasks are processed, which AI models are used, and how scheduling works. You can find it under **Settings > Task Management**. ![Task Management settings page](/_astro/settings-tasks.D13DsB_8_xqmrn.webp) ## LLM Models [Section titled “LLM Models”](#llm-models) This section lets you choose which AI models Errand uses for different purposes. For guidance on which models to select and what providers are available, see the [AI Models](/docs/ai-models/) guide. ### Title Generation Model [Section titled “Title Generation Model”](#title-generation-model) The model used to automatically generate short, descriptive titles for your tasks. A lighter, faster model is recommended here since title generation is a simple task. For example, `claude-haiku` works well for this purpose. ### Default Model [Section titled “Default Model”](#default-model) This is the main model that agents use when executing tasks. Choose a model that balances capability with speed for your typical workload. For example, `claude-sonnet` is a good general-purpose choice. ### Transcription Model [Section titled “Transcription Model”](#transcription-model) If you want to create tasks using your voice, select a **Whisper-compatible** transcription model here. Once configured, Errand will accept audio input and automatically transcribe it into a task description. Leave this blank if you do not plan to use voice input. ### LLM Timeout [Section titled “LLM Timeout”](#llm-timeout) The number of seconds Errand will wait for a response from the AI model before timing out. The default is **30 seconds**, which works well for cloud-hosted models. If you are running models locally (for example, through Ollama), you may need to increase this value to give the model extra time to load into memory and generate a response. A value of 120 seconds or more is recommended for local models. ## Task Management [Section titled “Task Management”](#task-management) This section controls general task processing behavior. ### Timezone [Section titled “Timezone”](#timezone) Set your local timezone so that scheduled tasks run at the correct time. This is especially important if you use Errand’s scheduling features to run tasks at specific times of day. ### Archive After (Days) [Section titled “Archive After (Days)”](#archive-after-days) Completed tasks are automatically moved to the archive after this many days. The default is **3 days**. Archived tasks are still accessible but are kept out of your main task list to reduce clutter. Increase this value if you like to keep completed tasks visible for longer, or decrease it if you prefer a cleaner task list. ### Task Runner Log Level [Section titled “Task Runner Log Level”](#task-runner-log-level) Controls how detailed the agent’s execution logs are. The available levels are: * **INFO** — Standard logging. Shows key steps and results. This is the default and is recommended for most users. * **DEBUG** — Verbose logging. Shows detailed internal operations. Useful for troubleshooting issues. * **WARNING** — Only shows warnings and errors. * **ERROR** — Only shows errors. If you are ever troubleshooting a task that is not behaving as expected, temporarily switching to **DEBUG** can help you understand what the agent is doing at each step. --- # Task Profiles > Create specialized profiles for different types of tasks. Task Profiles let you create specialized configurations for different types of work. Instead of using the same AI model and settings for every task, you can set up profiles that tailor the agent’s behavior to specific situations. You can find this page under **Settings > Task Profiles**. ![Task Profiles settings page](/_astro/settings-profiles.-ax6M6B7_2f05Sv.webp) ## Why Use Profiles? [Section titled “Why Use Profiles?”](#why-use-profiles) Different tasks have different needs. For example: * A **Research** profile might use a powerful model with access to web search tools, giving the agent time to think deeply and gather information. * A **Quick Reply** profile might use a fast, lightweight model with minimal tools, so you get a near-instant response. * A **Code Review** profile might use a capable model with access to your Git repository, but no need for web search or email. Profiles give you this flexibility without having to change your global settings every time. ## What Each Profile Can Configure [Section titled “What Each Profile Can Configure”](#what-each-profile-can-configure) When you create a profile, you can customize the following options: * **Name** — A short, descriptive name for the profile (for example, “Research” or “Quick Reply”). * **Description** — A brief explanation of what this profile is for. * **Match Rules** — Conditions that automatically assign incoming tasks to this profile based on the task description. For example, you could set a rule so that any task containing the word “research” is automatically handled by your Research profile. * **Model** — Which LLM model to use for tasks in this profile. This can be different from your default model. * **System Prompt** — Custom instructions specific to this type of task. These are used instead of (or in addition to) the global system prompt. * **Max Turns** — A limit on how many reasoning iterations the agent can take. This overrides the global setting and is useful for keeping simpler tasks from running too long. * **Reasoning Effort** — Controls how much the AI “thinks” before responding. Choose from **low**, **medium**, or **high**. Lower effort means faster responses; higher effort means more thorough reasoning. * **MCP Servers** — Choose which tool servers are available to the agent. For example, you might give a Research profile access to web search, while a Quick Reply profile has no external tools at all. * **Skills** — Select which skills are available to agents working under this profile. ## Creating a Profile [Section titled “Creating a Profile”](#creating-a-profile) 1. Click the **Add Profile** button. 2. Fill in the name, description, and any other fields you want to customize. 3. Set up match rules if you want tasks to be automatically assigned to this profile. 4. Click **Create**. ![Add Profile form showing all available configuration options](/_astro/settings-profiles-form.Jn4tIKCw_KpyLU.webp) ## How Tasks Are Assigned to Profiles [Section titled “How Tasks Are Assigned to Profiles”](#how-tasks-are-assigned-to-profiles) There are two ways a task can use a profile: * **Automatic matching** — When a new task is created, Errand checks the task description against the match rules of all your profiles. If a match is found, that profile is automatically applied. * **Manual assignment** — You can manually select a profile when creating or editing a task. If no profile matches and none is manually selected, the task uses your **default settings** from the [Task Management](/docs/docs/configuration/task-management/) page. ## Cloud Storage and Profiles [Section titled “Cloud Storage and Profiles”](#cloud-storage-and-profiles) If you have cloud storage integrations configured (such as Google Drive or OneDrive), profiles respect the MCP server filters you set. This means a profile that does not include cloud storage MCP servers will not have access to those files, giving you fine-grained control over what each type of task can access. --- # User Management > Manage authentication, users, and access control. The User Management page lets you control how people log in to Errand and what they can do once they are in. You can find it under **Settings > User Management**. ![User Management settings page](/_astro/settings-users.ChjmIetn_2aMrOM.webp) ## Authentication Modes [Section titled “Authentication Modes”](#authentication-modes) Errand supports two ways for users to log in: ### 1. Local Authentication (Default) [Section titled “1. Local Authentication (Default)”](#1-local-authentication-default) This is the simplest option. Users log in with a username and password that is stored directly in Errand. When you first set up Errand, an admin account is created automatically. If you are running Errand via Docker or Kubernetes, you can set the initial admin credentials using the `ADMIN_USERNAME` and `ADMIN_PASSWORD` environment variables in your deployment configuration. ### 2. SSO via OpenID Connect [Section titled “2. SSO via OpenID Connect”](#2-sso-via-openid-connect) For organizations that use a centralized identity provider (such as Keycloak, Okta, or Azure AD), Errand supports Single Sign-On through the **OpenID Connect** (OIDC) protocol. This lets your team log in with their existing organizational credentials and manage roles from one central place. ## Setting Up SSO [Section titled “Setting Up SSO”](#setting-up-sso) To enable SSO, fill in the following fields in the **Authentication Mode** section: 1. **Discovery URL** — Your OIDC provider’s discovery endpoint. This is usually a URL that ends with `/.well-known/openid-configuration`. For example: `https://auth.example.com/realms/myrealm/.well-known/openid-configuration` 2. **Client ID** — The OAuth client ID that your identity provider has assigned to Errand. You will get this when you register Errand as an application in your identity provider. 3. **Client Secret** — The OAuth client secret for Errand. This is provided alongside the Client ID by your identity provider. 4. **Roles Claim** — The JSON path to the roles array in the JWT token. The default value is `resource_access.errand.roles`, which works with Keycloak out of the box. If your identity provider uses a different structure, update this path accordingly. Once you have filled in these fields: 1. Click **Test Connection** to verify that Errand can communicate with your identity provider. This will confirm that your discovery URL, client ID, and client secret are correct. 2. If the test passes, click **Save & Enable SSO** to activate single sign-on. After SSO is enabled, users will see an SSO login option on the login page. ## Local Admin Account [Section titled “Local Admin Account”](#local-admin-account) The **Local Admin Account** section shows your current admin username and lets you change the admin password. To change your password: 1. Enter your **current password**. 2. Enter your **new password**. 3. Click **Save**. Even when SSO is enabled, the local admin account remains available as a fallback login method. ## User Roles [Section titled “User Roles”](#user-roles) Errand has two user roles: * **Admin** — Full access to all settings, user management, and system configuration. Admins can also create and manage tasks. * **User** — Can create and manage their own tasks, but cannot access system settings or manage other users. ### How Roles Are Assigned [Section titled “How Roles Are Assigned”](#how-roles-are-assigned) * **With Local Authentication** — The initial admin account is created during setup. Additional users can be created and assigned roles by an admin. * **With SSO** — Roles are managed by your identity provider. Map the `admin` and `user` roles to users or groups in your identity provider’s configuration. Errand reads these roles from the JWT token using the Roles Claim path described above. --- # Docker Install Docker Compose is the quickest way to run Errand AI on any machine with Docker installed. It sets up all the required services in containers and gets you to a working system in just a few steps. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * [Docker](https://docs.docker.com/get-docker/) installed and running * [Docker Compose](https://docs.docker.com/compose/install/) (included with Docker Desktop, or install separately on Linux) * An API key from at least one LLM provider (e.g. [Anthropic](https://console.anthropic.com/), [OpenAI](https://platform.openai.com/)) * (Optional) API keys for an LLM provider providing transcription models (eg. Groq’s whisper-large-v3) * (Optional) API keys or credentials for any integrations you want to use (e.g. Google Drive, OneDrive, Slack) These instructions assume that you will use LiteLLM to manage your connections to LLM providers. If you want to connect Errand directly to an LLM provider without using LiteLLM, see the [Advanced Configuration](#advanced-configuration) section below. ## Step 1: Clone the repository [Section titled “Step 1: Clone the repository”](#step-1-clone-the-repository) ```bash git clone https://github.com/errand-ai/errand.git cd errand/deploy ``` ## Step 2: Configure environment variables [Section titled “Step 2: Configure environment variables”](#step-2-configure-environment-variables) 1. Copy the example environment file: ```bash cp .env.example .env ``` 2. Open `.env` in a text editor and set the following values: | Variable | Description | Default | | --------------------------- | --------------------------------------------------- | --------------------- | | `ADMIN_USERNAME` | Username for the admin account | `admin` | | `ADMIN_PASSWORD` | Password for the admin account | `changeme` | | `CREDENTIAL_ENCRYPTION_KEY` | Encryption key for stored credentials (see below) | — | | `LITELLM_MASTER_KEY` | Master key for LiteLLM proxy authentication | `sk-12345678` | | `OPENAI_BASE_URL` | Base URL for your LLM provider (or a LiteLLM proxy) | `http://litellm:4000` | | `OPENAI_API_KEY` | Your LLM provider API key | — | 3. Generate an encryption key by running this command in your terminal: ```bash python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" ``` Copy the output and paste it as the value for `CREDENTIAL_ENCRYPTION_KEY` in your `.env` file. Note If you do not have Python installed, you can use any Fernet key generator. The key must be a valid 32-byte URL-safe base64-encoded string. ## Step 3: Configure LLM provider (LiteLLM) [Section titled “Step 3: Configure LLM provider (LiteLLM)”](#step-3-configure-llm-provider-litellm) The easiest way to connect Errand to an LLM provider is through LiteLLM, which acts as a proxy and unified interface for multiple providers. To set this up: ```bash docker compose up litellm ``` This will start the PostgreSQL and LiteLLM services. You can then access the LiteLLM dashboard at to add your LLM provider API keys and configure models. The default ‘admin’ password for the LiteLLM dashboard is `sk-12345678`, but you can change this by setting a different value for `LITELLM_MASTER_KEY` in your `.env` file. There are 2 steps we need to do in the LiteLLM dashboard: ### Step A: Add an LLM provider [Section titled “Step A: Add an LLM provider”](#step-a-add-an-llm-provider) The first step is to add a credential for your LLM provider, then create a model entry that uses that credential. 1. Go to the “Models + Endpoints” page and select the “LLM Credentials”tab and click “Add Credential” 2. Choose your provider from the dropdown (e.g. OpenAI, Anthropic, Groq, etc.) 3. Enter a name for this credential (e.g. “OpenAI Account”) and paste your API key 4. Click “Add Credential” 5. Select the “Add Model” tab. 6. Choose the provider you just added the credential for. 7. Choose the credential you just created from the dropdown, 8. then select a model to add (e.g. `gpt-4`, `gemini-2.5-flash`, `groq-whisper-large-v3`, etc.) 9. Click “Test Connection” to verify that LiteLLM can connect to the provider with the provided API key. You should see a success message if everything is correct. 10. Click “Add Model” to save. 11. Copy the “Model Name” value (e.g. `gpt-4`) and set it as the value for `HINDSIGHT_API_LLM_MODEL` in your `.env` file. Repeat steps 5-10 for any additional models you want to use. For help deciding which models to add, see the [AI Models](/docs/ai-models/) guide. ### Step B: Create Virtual Keys [Section titled “Step B: Create Virtual Keys”](#step-b-create-virtual-keys) The second step is to create “virtual keys” that the Errand and Hindsight services will use to access the LLM provider through LiteLLM. This allows you to rotate or change your actual API keys in LiteLLM without needing to update the Errand configuration. 1. Go to the “Virtual Keys” page in the LiteLLM dashboard. 2. Click “Create New Key”. 3. Select “Service Account” as the key owner. 4. Enter “errand” as the service account ID. 5. In the Models section, you can either select specific models that this key should have access to, or select “All Team Models”. 6. Click “Create Key” to generate the virtual key. 7. Copy the generated virtual key value (it will look like `sk-xxxxxx`) and paste it into the `OPENAI_API_KEY` variable in your `.env` file. ## Step 4: Start Errand [Section titled “Step 4: Start Errand”](#step-4-start-errand) Run the following command from the project directory to start all the remaining services: ```bash docker compose up ``` Docker Compose will start the following services: | Service | Purpose | | -------------------- | -------------------------------------------- | | **PostgreSQL** | Database for tasks, users, and configuration | | **LiteLLM** | Proxy for connecting to LLM providers | | **Hindsight** | Persistent memory for AI agents | | **Valkey** | In-memory cache for real-time coordination | | **Errand Server** | API server and web UI (port 8000) | | **Google Drive MCP** | File access for Google Drive integration | | **OneDrive MCP** | File access for OneDrive integration | Wait until you see log messages indicating that the server is ready. ## Step 4: Open the Errand UI [Section titled “Step 4: Open the Errand UI”](#step-4-open-the-errand-ui) 1. Open your web browser 2. Navigate to 3. Log in with the admin credentials you set in your `.env` file (default: `admin` / `changeme`) 4. Select the “Settings” page and the “Task Management” tab. 5. You should see LiteLLM listed as the LLM provider. Select the model to use for the task description parsing and initial processing. 6. Select the “Default Model” to use for task execution. This can be the same model or a different one from the one used for task management. 7. (Optional) If you added a transcription model in LiteLLM, select that model in the “Transcription Model” dropdown to enable audio transcription capabilities. 8. (Optional) If you want to use any integrations that require the Google Drive MCP or OneDrive MCP, go to the “Integrations” tab and enable those services by providing the necessary credentials. You are now ready to create and run tasks with Errand AI. ## Stopping Errand [Section titled “Stopping Errand”](#stopping-errand) To stop all services, press `Ctrl+C` in the terminal where Docker Compose is running, or run: ```bash docker compose down ``` To stop and also remove stored data (database, cache), add the `-v` flag: ```bash docker compose down -v ``` ## Scaling workers [Section titled “Scaling workers”](#scaling-workers) Errand supports horizontal scaling — you can add more worker replicas to execute tasks in parallel. For example, to run 3 workers: ```bash docker compose up --build --scale worker=3 ``` Each worker picks up tasks independently, so more workers means more tasks can run at the same time. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | `port is already allocated` error | Another application is using port 8000. Change the port mapping in `docker-compose.yml` or stop the conflicting application | | Services restart repeatedly | Check logs with `docker compose logs ` to identify the failing service. Common causes are missing environment variables or invalid API keys | | Cannot log in with default credentials | Confirm that `ADMIN_USERNAME` and `ADMIN_PASSWORD` are set correctly in your `.env` file and restart with `docker compose up` | | LLM errors during task execution | Verify that `OPENAI_API_KEY` and `OPENAI_BASE_URL` are correct. Check that your account has available credits with your LLM provider | | `CREDENTIAL_ENCRYPTION_KEY` error | Make sure you generated a valid Fernet key and pasted the full value into `.env` with no extra spaces or line breaks | --- # Helm Install Errand can be deployed to any Kubernetes cluster using its official Helm chart. This is the recommended approach for production environments, teams, and anywhere you need high availability or autoscaling. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * A running Kubernetes cluster (any provider — cloud or local) * [Helm 3](https://helm.sh/docs/intro/install/) installed on your machine * [kubectl](https://kubernetes.io/docs/tasks/tools/) configured to access your cluster * An API key from at least one LLM provider (e.g. [Anthropic](https://console.anthropic.com/), [OpenAI](https://platform.openai.com/)) ## Step 1: Create Kubernetes secrets [Section titled “Step 1: Create Kubernetes secrets”](#step-1-create-kubernetes-secrets) Before installing the chart, create the secrets that Errand needs. Run these commands, replacing the placeholder values with your own: 1. **Database credentials** — connection string for PostgreSQL: ```bash kubectl create secret generic errand-database \ --from-literal=DATABASE_URL="postgresql://user:password@hostname:5432/errand" ``` 2. **LLM provider credentials** — your API key: ```bash kubectl create secret generic errand-openai \ --from-literal=OPENAI_API_KEY="your-api-key-here" ``` 3. **Credential encryption key** — used to encrypt stored integration credentials: ```bash kubectl create secret generic errand-encryption \ --from-literal=CREDENTIAL_ENCRYPTION_KEY="$(python3 -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())')" ``` ## Step 2: Install the Helm chart [Section titled “Step 2: Install the Helm chart”](#step-2-install-the-helm-chart) Install the chart directly from the OCI registry: ```bash helm install errand oci://ghcr.io/errand-ai/charts/errand \ --set database.existingSecret=errand-database \ --set openai.existingSecret=errand-openai \ --set credentialEncryption.existingSecret=errand-encryption ``` Tip For your first install, set `worker.replicaCount=0` so you can verify the server is running before tasks start executing. Once you are satisfied, upgrade the release with workers enabled. ## Step 3: Configure values [Section titled “Step 3: Configure values”](#step-3-configure-values) The Helm chart is configured through a `values.yaml` file. Here are the key settings: ### Replicas and scaling [Section titled “Replicas and scaling”](#replicas-and-scaling) | Value | Description | Default | | --------------------- | ----------------------------------------- | ------- | | `server.replicaCount` | Number of API server replicas | `1` | | `worker.replicaCount` | Number of worker replicas | `1` | | `worker.maxTurns` | Maximum LLM reasoning turns per task | `200` | | `keda.enabled` | Enable KEDA-based autoscaling for workers | `false` | ### Secrets [Section titled “Secrets”](#secrets) | Value | Description | | ------------------------------------- | -------------------------------------------------------- | | `database.existingSecret` | Kubernetes secret containing `DATABASE_URL` | | `openai.existingSecret` | Kubernetes secret containing `OPENAI_API_KEY` | | `credentialEncryption.existingSecret` | Kubernetes secret containing `CREDENTIAL_ENCRYPTION_KEY` | ### Networking [Section titled “Networking”](#networking) | Value | Description | Default | | --------------------- | ------------------------------- | ------- | | `ingress.host` | Domain name for the Errand UI | — | | `ingress.tls.enabled` | Enable HTTPS using cert-manager | `false` | ### Built-in services [Section titled “Built-in services”](#built-in-services) | Value | Description | Default | | ------------------ | ------------------------------- | ------- | | `valkey.enabled` | Deploy a built-in Valkey cache | `true` | | `gdrive.enabled` | Enable Google Drive integration | `false` | | `onedrive.enabled` | Enable OneDrive integration | `false` | To use a custom values file: ```bash helm install errand oci://ghcr.io/errand-ai/charts/errand \ -f values.yaml ``` ## Step 4: Verify the installation [Section titled “Step 4: Verify the installation”](#step-4-verify-the-installation) 1. Check that the pods are running: ```bash kubectl get pods -l app.kubernetes.io/name=errand ``` 2. If you configured an ingress, open `https://your-domain` in your browser. Otherwise, use port forwarding: ```bash kubectl port-forward svc/errand-server 8000:8000 ``` 3. Navigate to and log in ## How task execution works [Section titled “How task execution works”](#how-task-execution-works) The worker uses **Kubernetes Jobs** to execute each task in an isolated pod. This means: * Each task runs in its own container with its own resources * A failed task does not affect other running tasks * The worker’s ServiceAccount needs RBAC permissions to create and manage Jobs, ConfigMaps, and Pods The Helm chart automatically creates the required ServiceAccount and RBAC roles. If you are using a custom ServiceAccount, make sure it has permissions for `jobs`, `configmaps`, and `pods` in the Errand namespace. ## Database options [Section titled “Database options”](#database-options) The chart does not include a built-in PostgreSQL instance. You need to provide your own database. Two common options: * **Managed database** — use a cloud-hosted PostgreSQL service (e.g. AWS RDS, Google Cloud SQL, Azure Database for PostgreSQL) and pass the connection string via the `database.existingSecret` * **CloudNativePG** — deploy PostgreSQL on Kubernetes using the [CloudNativePG operator](https://cloudnative-pg.io/), which handles backups, failover, and high availability ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | Pods stuck in `Pending` state | Check for resource constraints with `kubectl describe pod `. The cluster may not have enough CPU or memory available | | Server pod crashes on startup | Check logs with `kubectl logs `. The most common cause is a missing or incorrect `DATABASE_URL` in the database secret | | Worker cannot create task Jobs | Verify the worker’s ServiceAccount has the required RBAC permissions for Jobs, ConfigMaps, and Pods | | Cannot reach the UI through ingress | Confirm that `ingress.host` is set correctly, DNS points to your cluster, and (if using TLS) cert-manager has issued a certificate | | LLM errors during task execution | Verify the `OPENAI_API_KEY` secret is correct and your account has available credits with your LLM provider | | KEDA autoscaling not working | Ensure [KEDA](https://keda.sh/) is installed in your cluster and `keda.enabled` is set to `true` in your values | --- # MacOS Install > Install Errand AI on MacOS using the Errand Desktop app. Errand Desktop is a lightweight menu bar application that runs Errand AI locally on your Mac. It handles all the infrastructure for you — no terminal commands required. The app stays out of your way in the menu bar (no dock icon) and manages the full lifecycle of Errand’s services. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * **macOS 26+** (Tahoe) with **Apple Silicon** (M1 or later) for native container support * For older Intel-based Macs, [Docker Desktop](https://www.docker.com/products/docker-desktop/) or [Colima](https://github.com/abiosoft/colima) can be used as a fallback container runtime * An API key from at least one LLM provider (e.g. [Anthropic](https://console.anthropic.com/), [OpenAI](https://platform.openai.com/)) ## Step 1: Download Errand Desktop [Section titled “Step 1: Download Errand Desktop”](#step-1-download-errand-desktop) 1. Go to the [Errand Desktop releases page](https://github.com/errand-ai/errand-desktop/releases) 2. Download the latest `.dmg` file 3. Open the `.dmg` and drag **Errand Desktop** into your **Applications** folder 4. Launch the app from Applications — you will see a new icon appear in your menu bar ## Step 2: Complete the Setup Wizard [Section titled “Step 2: Complete the Setup Wizard”](#step-2-complete-the-setup-wizard) The first time you launch Errand Desktop, a Setup Wizard walks you through everything. It has 8 steps: 1. **Welcome** — a brief introduction to Errand AI 2. **Container runtime selection** — choose **Apple Containerization** if you have Apple Silicon, or **Docker** if you are on an older Intel Mac 3. **LLM configuration** — enter your API key for at least one LLM provider (e.g. Anthropic, OpenAI) 4. **LiteLLM startup** — optionally enable LiteLLM, a proxy that translates between different LLM providers so you can mix and match models 5. **Agent memory configuration** — optionally enable Hindsight, a service that gives your AI agents persistent memory across tasks 6. **Version / image tag selection** — choose which version of Errand to install (the latest stable version is selected by default) 7. **Container image downloading** — the app downloads the required container images (this may take a few minutes on the first run) 8. **Done** — setup is complete and your services are starting up ## Step 3: Wait for services to start [Section titled “Step 3: Wait for services to start”](#step-3-wait-for-services-to-start) After the wizard finishes, Errand Desktop starts the services in the correct order: 1. **PostgreSQL** (database) 2. **Valkey** (cache) 3. **LiteLLM** (LLM proxy, if enabled) 4. **Backend** (API server) 5. **Worker** (task runner) The menu bar icon shows the current health status of your services. When everything is green, Errand is ready to use. ## Step 4: Open the Errand UI [Section titled “Step 4: Open the Errand UI”](#step-4-open-the-errand-ui) 1. Open your web browser 2. Navigate to 3. Log in with the credentials you configured during setup You are now ready to create and run tasks with Errand AI. ## Settings [Section titled “Settings”](#settings) Click the menu bar icon and select **Settings** to adjust your configuration at any time. The settings are organized into four sections: | Section | What you can configure | | ----------- | ------------------------------------------ | | **General** | Container runtime, launch at login | | **LLM** | LLM provider, API keys, model selection | | **Memory** | Enable or disable Hindsight (agent memory) | | **Ports** | Customize the ports used by each service | ## Viewing logs [Section titled “Viewing logs”](#viewing-logs) Errand Desktop includes a built-in log viewer that shows real-time logs from all running services. To open it, click the menu bar icon and select **Logs**. This is helpful for debugging if a service fails to start, or a task does not complete as expected. ## Where data is stored [Section titled “Where data is stored”](#where-data-is-stored) | What | Location | | ---------------- | -------------------------------------------------------- | | Application data | `~/Library/Application Support/ErrandDesktop/` | | Credentials | macOS Keychain (stored securely by the operating system) | ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | | App does not appear in the menu bar | Check that the app is running — open it from Applications. It has no dock icon, so it only appears in the menu bar | | Services fail to start | Open the log viewer to check for errors. Ensure your container runtime (Apple Containerization or Docker) is working | | Cannot connect to | Wait for all services to show as healthy in the menu bar. If the port is in use, change it in **Settings > Ports** | | LLM errors during task execution | Verify your API key is correct in **Settings > LLM**. Check that your account has available credits with your LLM provider | | Setup Wizard does not appear on first launch | Delete the folder at `~/Library/Application Support/ErrandDesktop/` and relaunch the app to reset | --- # Email > Connect an email account to send, read, and manage emails. Email integration gives agents the ability to read, send, forward, and manage emails via IMAP and SMTP. You can also configure Errand to automatically create tasks from incoming emails. Use a dedicated mailbox We strongly recommend setting up a **separate email account** for use with Errand rather than connecting your personal inbox. Giving an AI agent access to your personal email carries risk — it can read all your messages and, if misconfigured, could send or move emails unintentionally. A dedicated mailbox limits the blast radius and keeps your personal correspondence private. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * An email account with IMAP and SMTP access * An app-specific password is recommended (e.g. [Gmail App Passwords](https://support.google.com/accounts/answer/185833), or equivalent for your provider) ## Configuration [Section titled “Configuration”](#configuration) 1. Open the Errand UI and go to **Settings > Integrations** 2. Find the **Email** card and click it 3. Fill in the following fields: | Field | Description | Example | | ------------------------- | -------------------------------------------------------------------------------------- | ----------------------- | | **Security** | Encryption method for email connections | SSL/TLS or STARTTLS | | **IMAP Server** | Your email provider’s IMAP server address | `imap.gmail.com` | | **IMAP Port** | The IMAP server port | `993` | | **SMTP Server** | Your email provider’s SMTP server address | `smtp.gmail.com` | | **SMTP Port** | The SMTP server port | `465` | | **Email Address** | The email account to connect | `you@gmail.com` | | **Password** | Your password or app-specific password | — | | **Task Profile** | Which [task profile](/docs/task-profiles) handles email-triggered tasks | Select from dropdown | | **Poll Interval** | How often to check for new emails (minimum 60 seconds) | `120` (seconds) | | **Authorised Recipients** | Whitelist of email addresses the agent is allowed to send or forward to (one per line) | `colleague@company.com` | 4. Click **Test & Save** — Errand will verify both IMAP and SMTP connectivity Caution The **Authorised Recipients** list is a security measure. Agents can only send or forward emails to addresses on this list. This prevents agents from emailing unintended recipients. ## Poll interval and IMAP IDLE [Section titled “Poll interval and IMAP IDLE”](#poll-interval-and-imap-idle) The poll interval sets how frequently Errand checks for new emails. If your email server supports **IMAP IDLE** (most modern servers do), Errand will receive near-instant notifications of new emails, and the poll interval acts as a fallback. ## What agents can do with email [Section titled “What agents can do with email”](#what-agents-can-do-with-email) Once connected, agents have the following capabilities during task execution: * **List emails** — browse messages in your inbox and other folders * **Read email content** — open and read individual messages * **Send emails** — compose and send new emails (to authorised recipients only) * **Forward emails** — forward messages to authorised recipients * **Move emails** — move messages between folders * **List folders** — see available mailbox folders Certain folders (Trash, Junk, Spam) are automatically excluded from agent access. ## Auto-creating tasks from emails [Section titled “Auto-creating tasks from emails”](#auto-creating-tasks-from-emails) When the email integration is active, incoming emails can automatically create new tasks. The task will use the **Task Profile** you selected during configuration. This is useful for workflows like support tickets, approvals, or any email-driven process. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | Authentication failure | Use an app-specific password instead of your regular password — most providers require this when IMAP access is enabled | | Connection timeout | Double-check the server addresses and ports — common IMAP ports are 993 (SSL) and 143 (STARTTLS), common SMTP ports are 465 (SSL) and 587 (STARTTLS) | | Can’t send emails | Verify your SMTP configuration and make sure the recipient is listed in **Authorised Recipients** | | Emails not being detected | Check the poll interval and ensure IMAP access is enabled in your email provider’s settings | --- # Git Repositories > Configure Git repository access for task agents. Git repository access allows agents to clone, read, and work with Git repositories during task execution. Errand uses SSH keys to authenticate with your Git hosting service. ## How it works [Section titled “How it works”](#how-it-works) When you install Errand, it automatically generates a unique SSH key pair for Git operations. You grant access to repositories by adding Errand’s public key to your Git hosting service. There are two ways to do this, depending on how many repositories you need to give Errand access to: * **Option A: Deploy keys** — best when you only need access to one or two specific repositories. * **Option B: User account SSH key** — best when you need access to many repositories or an entire organisation. ## Copy the SSH public key [Section titled “Copy the SSH public key”](#copy-the-ssh-public-key) Whichever option you choose, you’ll need Errand’s public key first: 1. Open the Errand UI and go to **Settings > Security** 2. Find the **SSH Public Key** field 3. Copy the full public key value ## Option A: Deploy keys (per-repository) [Section titled “Option A: Deploy keys (per-repository)”](#option-a-deploy-keys-per-repository) Deploy keys grant access to a single repository. This is the simplest approach when you only need agents to work with one or two repos. ### GitHub [Section titled “GitHub”](#github) 1. Go to your repository on GitHub 2. Navigate to **Settings > Deploy keys** 3. Click **Add deploy key** 4. Enter a title (e.g. “Errand”) 5. Paste the SSH public key 6. Optionally check **Allow write access** if agents need to push changes 7. Click **Add key** ### GitLab [Section titled “GitLab”](#gitlab) 1. Go to your project on GitLab 2. Navigate to **Settings > Repository > Deploy keys** 3. Enter a title, paste the SSH public key, and optionally grant write permissions 4. Click **Add key** ### Bitbucket [Section titled “Bitbucket”](#bitbucket) 1. Go to your repository on Bitbucket 2. Navigate to **Repository settings > Access keys** 3. Click **Add key** 4. Enter a label and paste the SSH public key 5. Click **Add key** Note Deploy keys are per-repository. You’ll need to repeat this for each repository you want agents to access. If you have more than a handful of repositories, consider Option B instead. ## Option B: User account SSH key (multi-repository) [Section titled “Option B: User account SSH key (multi-repository)”](#option-b-user-account-ssh-key-multi-repository) If you need Errand to access many repositories — or all repositories in an organisation — you can add the SSH key to a user account instead. Any repository that user has access to will be available to Errand. Use a dedicated account Do not add Errand’s SSH key to your own personal account. This would give agents access to **all** of your private repositories. Instead, create a **dedicated machine user account** (e.g. “errand-bot”) and add the SSH key to that account. Then grant the machine user access only to the repositories or organisations that Errand needs. ### GitHub [Section titled “GitHub”](#github-1) 1. Create a new GitHub account to act as your machine user (e.g. “errand-bot”) 2. Log in as the machine user 3. Go to **Settings > SSH and GPG keys** 4. Click **New SSH key** 5. Enter a title (e.g. “Errand”) and paste the SSH public key 6. Click **Add SSH key** 7. Back on your main account, invite the machine user as a **collaborator** on the repositories it needs access to, or add it as a **member** of your organisation ### GitLab [Section titled “GitLab”](#gitlab-1) 1. Create a new GitLab account for the machine user 2. Go to **Preferences > SSH Keys** 3. Paste the SSH public key and click **Add key** 4. Add the machine user to the projects or groups it needs access to ### Bitbucket [Section titled “Bitbucket”](#bitbucket-1) 1. Create a new Bitbucket account for the machine user 2. Go to **Personal settings > SSH keys** 3. Click **Add key** and paste the SSH public key 4. Add the machine user to the relevant repositories or workspaces ## Write access [Section titled “Write access”](#write-access) If your tasks require agents to push commits, branches, or tags, make sure the key has **write access**: * For **deploy keys**: check the write access option when adding the key * For **user account keys**: ensure the machine user has write permissions on the repository (e.g. “Write” or “Maintainer” role) Without write access, agents can only clone and read from repositories. ## SSH hosts [Section titled “SSH hosts”](#ssh-hosts) By default, Errand uses SSH for connections to `github.com` and `bitbucket.org`. All other hosts use HTTPS. If you use a different Git hosting service over SSH (e.g. a self-hosted GitLab instance), you can configure additional SSH hosts via the `git_ssh_hosts` setting. ## What agents can do with Git [Section titled “What agents can do with Git”](#what-agents-can-do-with-git) During task execution, agents can: * **Clone repositories** to a local working directory * **Read files** and browse the repository structure * **Make changes** to files in the working copy * **Commit and push** changes back to the remote (if write access is enabled) ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | | ”Permission denied (publickey)” error | Check that the SSH public key from **Settings > Security** has been added as a deploy key or to the machine user’s account | | Host key verification failed | Ensure the Git host is included in the `git_ssh_hosts` setting, or use HTTPS instead | | Can’t push changes | Verify that **write access** is enabled on the deploy key, or that the machine user has write permissions | | No access to a repository | For deploy keys, check the key is on the correct repo. For user keys, check the machine user has been granted access | --- # GitHub > Connect GitHub to give agents access to your repositories. GitHub integration allows agents to interact with your GitHub repositories during task execution. Agents can browse repositories, read files, create issues, open pull requests, and more. Errand supports two authentication modes — choose the one that best fits your needs. ## Authentication modes [Section titled “Authentication modes”](#authentication-modes) | Mode | Best for | Key benefit | | ------------------------------- | ----------------------- | ------------------------------------- | | **Personal Access Token (PAT)** | Individual users | Simple setup | | **GitHub App** | Teams and organizations | Fine-grained permissions, audit trail | *** ## Option A: Personal Access Token (PAT) [Section titled “Option A: Personal Access Token (PAT)”](#option-a-personal-access-token-pat) Use a dedicated account Rather than generating a token from your own GitHub account, consider creating a **dedicated machine user account** (e.g. “errand-bot”) and generating the token from there. This lets you control exactly which repositories and permissions Errand has access to, without exposing your personal account’s full access. ### Step 1: Create a fine-grained token [Section titled “Step 1: Create a fine-grained token”](#step-1-create-a-fine-grained-token) 1. Go to [GitHub Settings > Developer settings > Personal access tokens > Fine-grained tokens](https://github.com/settings/tokens?type=beta) 2. Click **Generate new token** 3. Configure: * **Token name**: e.g. “Errand” * **Expiration**: choose an appropriate duration * **Repository access**: select the repositories you want agents to access * **Permissions**: grant the repository permissions your workflows need (e.g. Contents read/write, Issues read/write, Pull requests read/write) 4. Click **Generate token** and copy the value immediately ### Step 2: Enter the token in Errand [Section titled “Step 2: Enter the token in Errand”](#step-2-enter-the-token-in-errand) 1. Open the Errand UI and go to **Settings > Integrations** 2. Find the **GitHub** card and click it 3. Select **Personal Access Token** as the authentication mode 4. Paste your token 5. Click **Test & Save** — Errand will verify the token against the GitHub API *** ## Option B: GitHub App [Section titled “Option B: GitHub App”](#option-b-github-app) GitHub Apps provide more granular control over permissions and work well for teams. ### Step 1: Create a GitHub App [Section titled “Step 1: Create a GitHub App”](#step-1-create-a-github-app) 1. Go to [github.com/settings/apps](https://github.com/settings/apps) (or your organization’s settings) 2. Click **New GitHub App** 3. Configure: * **App name**: e.g. “Errand” * **Homepage URL**: your Errand instance URL * **Webhook**: uncheck **Active** (Errand doesn’t need webhook events from the app) 4. Under **Permissions**, grant the repository permissions your workflows need 5. Click **Create GitHub App** ### Step 2: Generate a private key [Section titled “Step 2: Generate a private key”](#step-2-generate-a-private-key) 1. On the app’s settings page, scroll to **Private keys** 2. Click **Generate a private key** 3. A `.pem` file will download — keep this safe ### Step 3: Install the app [Section titled “Step 3: Install the app”](#step-3-install-the-app) 1. Go to your app’s settings page and click **Install App** in the left sidebar 2. Choose the account or organization to install it on 3. Select which repositories the app can access 4. Click **Install** 5. Note the **Installation ID** from the URL after installation (the number at the end of the URL) ### Step 4: Enter credentials in Errand [Section titled “Step 4: Enter credentials in Errand”](#step-4-enter-credentials-in-errand) 1. Open the Errand UI and go to **Settings > Integrations** 2. Find the **GitHub** card and click it 3. Select **GitHub App** as the authentication mode 4. Enter: * **App ID** — found on the app’s settings page (General > About) * **Private Key** — paste the contents of the `.pem` file * **Installation ID** — from Step 3 5. Click **Test & Save** — Errand will verify the credentials ## How it works [Section titled “How it works”](#how-it-works) * Credentials are encrypted at rest using your Errand credential encryption key * The agent authenticates with GitHub during task execution using the stored credentials * For GitHub Apps, Errand generates short-lived installation tokens automatically ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | -------------------------------- | ----------------------------------------------------------------------------------------- | | ”Bad credentials” error | Your token may have expired — regenerate it in GitHub and update it in Errand | | ”Insufficient permissions” error | Check that your token or GitHub App has the required permission scopes for the operation | | GitHub App not working | Verify the app is installed on the target repositories and the Installation ID is correct | | Token expired | Fine-grained tokens have an expiry date — create a new one and update it in Errand | --- # Google Drive > Connect Google Drive to give task-runner agents read/write access to your files Google Drive integration gives task-runner agents read/write access to files in a user’s Google Drive. When connected, agents can list, read, create, update, and delete files and folders during task execution. The integration uses a dedicated [Google Drive MCP server](https://github.com/devops-consultants/google-drive-mcp-server) that is deployed alongside Errand. The server communicates with the Google Drive API using OAuth tokens managed by Errand. Use a dedicated account We recommend connecting a **dedicated Google account** rather than your personal one. Errand agents will have full read/write access to all files in the connected Drive, including the ability to delete them. Using a separate account lets you share only the specific files and folders Errand needs, keeping the rest of your personal files out of reach. Use Errand Cloud for Connecting Setting up OAuth credentials for Google Drive requires a publicly accessible callback URL. If your Errand installation runs on a local network, **[Errand Cloud](/docs/cloud-service/cloud-authentication/)** can handle the authentication flow for you — no public URL needed. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * The Google Drive MCP server must be deployed (enabled by default in the Helm chart and docker-compose) * An OAuth 2.0 client must be registered in the Google Cloud Console * The user connecting their account must have a Google account with Google Drive access ## Step 1: Create a Google Cloud project [Section titled “Step 1: Create a Google Cloud project”](#step-1-create-a-google-cloud-project) 1. Go to the [Google Cloud Console](https://console.cloud.google.com/) 2. Click the project selector at the top and choose **New Project** 3. Give it a name (e.g. “Errand”) and click **Create** 4. Select the newly created project ## Step 2: Configure the OAuth consent screen [Section titled “Step 2: Configure the OAuth consent screen”](#step-2-configure-the-oauth-consent-screen) 1. Navigate to **APIs & Services > OAuth consent screen** 2. Choose the user type: * **Internal** — if all users are in your Google Workspace organization (no app review needed) * **External** — if users outside your organization need access (requires app review for production, or add test users) 3. Fill in the required fields: * **App name**: e.g. “Errand” * **User support email**: your email * **Developer contact email**: your email 4. On the **Scopes** step, click **Add or remove scopes** and add: * `https://www.googleapis.com/auth/drive` (full Drive access) 5. If using **External** user type in testing mode, add your Google account email under **Test users** 6. Click **Save and Continue** through the remaining steps ## Step 3: Create OAuth credentials [Section titled “Step 3: Create OAuth credentials”](#step-3-create-oauth-credentials) 1. Navigate to **APIs & Services > Credentials** 2. Click **Create Credentials > OAuth client ID** 3. Configure: * **Application type**: Web application * **Name**: e.g. “Errand Web Client” * **Authorized redirect URIs**: Add your Errand callback URL: ```plaintext https:///api/integrations/google_drive/callback ``` For local development: ```plaintext http://localhost:8000/api/integrations/google_drive/callback ``` 4. Click **Create** and note the **Client ID** and **Client Secret** ## Step 4: Enable the Google Drive API [Section titled “Step 4: Enable the Google Drive API”](#step-4-enable-the-google-drive-api) 1. Navigate to **APIs & Services > Enabled APIs & services** 2. Click **Enable APIs and Services** 3. Search for “Google Drive API” and click **Enable** ## Step 5: Configure Errand [Section titled “Step 5: Configure Errand”](#step-5-configure-errand) Provide the OAuth credentials as environment variables to the Errand server. ### Docker Compose [Section titled “Docker Compose”](#docker-compose) Add to your `.env` file: ```bash GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=your-client-secret ``` These are already wired into the `errand` service in `docker-compose.yml`. ### Kubernetes (Helm) [Section titled “Kubernetes (Helm)”](#kubernetes-helm) Create a Kubernetes secret: ```bash kubectl create secret generic errand-gdrive-oauth \ --from-literal=GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com" \ --from-literal=GOOGLE_CLIENT_SECRET="your-client-secret" \ -n errand ``` Set the secret name in your Helm values: ```yaml gdrive: enabled: true existingSecret: errand-gdrive-oauth ``` ## Step 6: Connect your account [Section titled “Step 6: Connect your account”](#step-6-connect-your-account) 1. Open the Errand UI and navigate to **Settings > Integrations** 2. The **Google Drive** card should show a **Connect** button (if it’s greyed out, check that the environment variables are set and the MCP server is running) 3. Click **Connect** — you’ll be redirected to Google’s consent screen 4. Sign in and grant access to your Google Drive 5. You’ll be redirected back to Errand — the card should now show your connected account ## How it works [Section titled “How it works”](#how-it-works) Once connected: * The worker loads your Google Drive credentials before each task execution * If the OAuth access token has expired, the worker automatically refreshes it using the stored refresh token * The Google Drive MCP server is injected into the task-runner’s MCP configuration with a fresh Bearer token * The task-runner agent can use the MCP tools to interact with your Google Drive files * Cloud storage instructions are appended to the system prompt to guide the agent ## Task profile control [Section titled “Task profile control”](#task-profile-control) Cloud storage MCP servers participate in [task profile](/docs/task-profiles) filtering. If a profile specifies an `mcp_servers` list, the Google Drive server (`google_drive`) must be included for agents using that profile to access Drive files. Profiles with no `mcp_servers` filter include all available MCP servers by default. ## Disconnecting [Section titled “Disconnecting”](#disconnecting) To disconnect your Google Drive account: 1. Go to **Settings > Integrations** 2. Click **Disconnect** on the Google Drive card 3. The stored credentials are deleted from Errand You can also revoke access from Google’s side at [myaccount.google.com/permissions](https://myaccount.google.com/permissions). ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | --------------------------------------------- | -------------------------------------------------------------------------------------------------- | | Card is greyed out | Check that `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, and `GDRIVE_MCP_URL` are all set | | ”Provider not configured” error on Connect | The OAuth client credentials are not set in the server’s environment | | Consent screen shows “unverified app” warning | Normal for External apps in testing mode — click “Advanced” then “Go to (app name)“ | | Token refresh fails after some time | The user may have revoked access — disconnect and reconnect | | Agent reports auth errors during task | The access token may have expired mid-task (tasks longer than 1 hour) — this is a known limitation | --- # Jira > Connect Jira Cloud to automatically create tasks from Jira issues and report results back. Jira integration lets you delegate work from your Jira board to Errand’s AI agents. When a Jira issue matches your configured filters (issue type, label, project), Errand automatically creates a task, executes it, and posts the results back to the Jira issue as comments, status transitions, and label updates. ## Features [Section titled “Features”](#features) * **Webhook triggers** — automatically create tasks when Jira issues are created or updated * **Configurable filters** — match on event type, issue type, labels, and project key * **Completion actions** — comment results, transition status, assign issues, add labels * **Atlassian MCP tools** — give agents the ability to read and interact with Jira during task execution * **Bidirectional tracking** — Errand tracks the link between tasks and Jira issues for deduplication and callbacks ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * A **Jira Cloud** instance (Jira Server/Data Center is not supported) * A **service account** with an API token scoped to your Jira instance * A way for Jira to reach your Errand installation: * **Errand Cloud** (recommended) — the [Cloud Service](/docs/cloud-service) relays Jira webhooks to your local installation * **Self-managed** — expose your Errand server to the internet so Jira can deliver webhooks directly ## Overview [Section titled “Overview”](#overview) Setup has three parts: 1. **Connect Jira credentials** — so Errand can call the Jira API for completion actions 2. **Create a webhook trigger** — configure which Jira events create tasks and what happens on completion 3. **Register the webhook in Jira** — point Jira at your Errand webhook URL Optionally, you can also add the Atlassian MCP server to a task profile so that agents can interact with Jira issues during execution. *** ## Step 1: Create a Jira API Token [Section titled “Step 1: Create a Jira API Token”](#step-1-create-a-jira-api-token) 1. Log in to [id.atlassian.com](https://id.atlassian.com) with the account you want to use as the service account 2. Go to **Security > API tokens** 3. Click **Create API token** 4. Give it a label (e.g. “Errand”) and click **Create** 5. Copy the token — you won’t be able to see it again Service account Use a dedicated service account (e.g. `errand-bot@yourcompany.com`) rather than a personal account. This keeps the audit trail clean and lets you scope permissions appropriately. ## Step 2: Find Your Cloud ID [Section titled “Step 2: Find Your Cloud ID”](#step-2-find-your-cloud-id) Your Atlassian Cloud ID identifies your Jira instance. To find it: 1. Go to your Jira instance (e.g. `https://yourcompany.atlassian.net`) 2. Navigate to `https://yourcompany.atlassian.net/_edge/tenant_info` 3. Copy the `cloudId` value from the JSON response ## Step 3: Connect Jira in Errand [Section titled “Step 3: Connect Jira in Errand”](#step-3-connect-jira-in-errand) 1. Open the Errand UI and go to **Settings > Integrations** 2. Find the **Jira** card and click **Connect Jira** 3. Fill in: * **Site URL** — your Jira instance URL (e.g. `https://yourcompany.atlassian.net`) * **Cloud ID** — from Step 2 * **API Token** — from Step 1 * **Service Account Email** — the email address of the account that owns the API token 4. Click **Save & Verify** Errand verifies the token by calling the Jira API. If verification succeeds, the card shows “Connected” with the account display name. ## Step 4: Create a Webhook Trigger [Section titled “Step 4: Create a Webhook Trigger”](#step-4-create-a-webhook-trigger) 1. Go to **Settings > Task Generators** 2. In the **Webhook Triggers** section, click **Add Trigger** 3. Configure the trigger: ### Source and Name [Section titled “Source and Name”](#source-and-name) * **Source** — select “Jira” * **Name** — a descriptive name (e.g. “Jira Bug Triage”, “Story Analysis”) ### Task Profile [Section titled “Task Profile”](#task-profile) Select which [task profile](/docs/task-profiles) the agent should use when executing tasks from this trigger. The profile controls the model, system prompt, MCP tools, and skills available to the agent. ### Filters [Section titled “Filters”](#filters) Filters determine which Jira events create tasks. All filters are ANDed together — an event must match every configured filter. Leave a filter empty to match all values. | Filter | Description | Example | | --------------- | ------------------------------------ | ------------------------------------------ | | **Event Types** | Which Jira events to react to | `jira:issue_created`, `jira:issue_updated` | | **Issue Types** | Which issue types to match | `Story`, `Bug`, `Task`, `Feature`, `Epic` | | **Labels** | Trigger when an issue has this label | `errand`, `ai-review` | | **Projects** | Which Jira project keys to scope to | `SCRUM`, `WEBAPP` | Label filter behavior For `jira:issue_created` events, the label must be present on the issue at creation time. For `jira:issue_updated` events, the filter matches if the label is currently on the issue — it doesn’t need to have been added in that specific update. ### Completion Actions [Section titled “Completion Actions”](#completion-actions) Configure what Errand does when a task finishes: | Action | Description | | ----------------------------------- | --------------------------------------------------------- | | **Assign to service account** | Claims the Jira issue when the task starts | | **Add comment with task reference** | Posts a comment when the task starts and when it finishes | | **Comment output on complete** | Includes the full task output in the completion comment | | **Add label on complete** | Adds a label to the issue (e.g. `errand-done`) | | **Transition on complete** | Moves the issue to a target status (e.g. `Done`) | ### Webhook Secret [Section titled “Webhook Secret”](#webhook-secret) Click **Generate** to create a cryptographic secret, or paste your own. This secret is used for HMAC-SHA256 signature verification — Jira signs each webhook payload with it, and Errand verifies the signature before processing. The secret is stored encrypted and never shown again after the initial save. If you need to change it, generate a new one and update the webhook configuration in Jira. 4. Click **Save** ## Step 5: Register the Webhook in Jira [Section titled “Step 5: Register the Webhook in Jira”](#step-5-register-the-webhook-in-jira) 1. In Jira, go to **Settings** (gear icon) > **System** > **WebHooks** 2. Click **Create a WebHook** 3. Configure: * **Name** — e.g. “Errand” * **Status** — Enabled * **URL** — your Errand webhook URL: * **Direct**: `https://your-errand-instance/webhooks/jira` * **Errand Cloud**: the cloud relay URL shown on the trigger detail page in Errand * **Secret** — paste the webhook secret from Step 4 4. Under **Events**, select the events that match your trigger’s event type filters: * For `jira:issue_created` — check **Issue > created** * For `jira:issue_updated` — check **Issue > updated** 5. Optionally filter by JQL to limit which issues fire the webhook (e.g. `project = SCRUM`) 6. Click **Create** Testing Create a test issue in the matching project with the matching label and issue type. Check Errand’s task board — a new task should appear within a few seconds. If it doesn’t, check the server logs for filter rejection messages. *** ## Optional: Add Atlassian MCP Server to Task Profiles [Section titled “Optional: Add Atlassian MCP Server to Task Profiles”](#optional-add-atlassian-mcp-server-to-task-profiles) The webhook trigger handles inbound events and completion callbacks. If you also want the AI agent to **read and interact with Jira issues during task execution** (e.g. look up related issues, read comments, create sub-tasks), add the Atlassian MCP server to the task profile. 1. Go to **Settings > Agent Configuration** 2. Expand the **MCP Server Configuration** section 3. In the JSON text box, add the Atlassian MCP server. If the field is empty, paste this full configuration: ```json { "mcpServers": { "atlassian": { "url": "https://mcp.atlassian.com/v1/mcp", "headers": { "Authorization": "Bearer ${JIRA_API_TOKEN}" } } } } ``` If you already have other MCP servers configured, add the `"atlassian"` entry alongside them inside the existing `"mcpServers"` object. 4. Click **Save** The `${JIRA_API_TOKEN}` placeholder is automatically replaced with the API token from your Jira credentials (configured in Step 3) at task execution time. You don’t need to hardcode the token. Note The Atlassian MCP server is a hosted service provided by Atlassian. It gives AI agents tools to search issues, read issue details, create issues, add comments, and manage projects. See the [Atlassian MCP documentation](https://developer.atlassian.com/cloud/mcp/) for the full list of available tools. If you only want certain task profiles to have Jira access, add the MCP server to those specific profiles in **Settings > Task Profiles** rather than to the global agent configuration. The profile assigned to your webhook trigger controls which MCP servers are available during execution. *** ## How It Works [Section titled “How It Works”](#how-it-works) When everything is connected, the flow is: 1. A Jira issue is created or updated, matching your trigger filters 2. Jira sends a webhook to Errand (directly or via Cloud relay) 3. Errand verifies the HMAC signature and identifies the matching trigger 4. Errand creates a task with the issue summary, description, and the trigger’s task profile 5. The AI agent executes the task using the configured model, tools, and skills 6. On completion, Errand posts results back to the Jira issue (comments, transitions, labels) Each Jira issue creates at most one task — duplicate webhooks for the same issue are automatically deduplicated. *** ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | | ”Not Connected” on Jira card | Verify the Cloud ID, API token, and site URL in **Settings > Integrations > Jira** | | Webhooks arrive but no tasks created | Check the trigger’s filters — the server log shows which filter rejected the event and why (event type, issue type, labels, project) | | “Add Trigger” button is disabled | Jira credentials must be connected first — go to **Settings > Integrations** | | Completion comments not appearing | Verify the API token has permission to comment on issues in the target project | | Transition fails | The target status name must match an available transition exactly (case-insensitive). Check the issue’s current workflow for valid transitions | | `${JIRA_API_TOKEN}` not replaced | Ensure Jira credentials are saved in **Settings > Integrations > Jira** — the placeholder is resolved from those stored credentials | | Cloud relay returns 401 | The webhook secret in Jira must match the secret configured on the trigger in Errand | --- # OneDrive > Connect OneDrive to give task-runner agents read/write access to your files OneDrive integration gives task-runner agents read/write access to files in a user’s OneDrive. When connected, agents can list, read, create, update, and delete files and folders during task execution. The integration uses a dedicated [OneDrive MCP server](https://github.com/devops-consultants/one-drive-mcp-server) that is deployed alongside Errand. The server communicates with the Microsoft Graph API using OAuth tokens managed by Errand. Use a dedicated account We recommend connecting a **dedicated Microsoft account** rather than your personal one. Errand agents will have full read/write access to all files in the connected OneDrive, including the ability to delete them. Using a separate account lets you share only the specific files and folders Errand needs, keeping the rest of your personal files out of reach. Use Errand Cloud for Connecting Setting up OAuth credentials for OneDrive requires a publicly accessible callback URL. If your Errand installation runs on a local network, **[Errand Cloud](/docs/cloud-service/cloud-authentication/)** can handle the authentication flow for you — no public URL needed. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * The OneDrive MCP server must be deployed (enabled by default in the Helm chart and docker-compose) * An OAuth 2.0 app registration must be created in Microsoft Entra ID (formerly Azure AD) * The user connecting their account must have a Microsoft account with OneDrive access ## Step 1: Register an application in Microsoft Entra [Section titled “Step 1: Register an application in Microsoft Entra”](#step-1-register-an-application-in-microsoft-entra) 1. Go to the [Microsoft Entra admin center](https://entra.microsoft.com/) 2. Navigate to **Identity > Applications > App registrations** 3. Click **New registration** 4. Configure: * **Name**: e.g. “Errand OneDrive” * **Supported account types**: Choose based on your needs: * **Single tenant** — only users in your organization * **Multitenant** — users in any Microsoft Entra directory * **Multitenant + personal Microsoft accounts** — broadest access * **Redirect URI**: Select platform **Web** and enter: ```plaintext https:///api/integrations/onedrive/callback ``` For local development: ```plaintext http://localhost:8000/api/integrations/onedrive/callback ``` 5. Click **Register** ## Step 2: Note the application IDs [Section titled “Step 2: Note the application IDs”](#step-2-note-the-application-ids) On the app’s **Overview** page, note: * **Application (client) ID** — this is your `MICROSOFT_CLIENT_ID` * **Directory (tenant) ID** — this is your `MICROSOFT_TENANT_ID` If you selected **Multitenant** or **Multitenant + personal** in the previous step, you can use `common` as the tenant ID instead of the specific directory ID. ## Step 3: Create a client secret [Section titled “Step 3: Create a client secret”](#step-3-create-a-client-secret) 1. Navigate to **Certificates & secrets** 2. Under **Client secrets**, click **New client secret** 3. Add a description (e.g. “Errand”) and choose an expiry period 4. Click **Add** 5. **Copy the Value immediately** — it is only shown once. This is your `MICROSOFT_CLIENT_SECRET` Caution The secret value is only displayed once after creation. If you lose it, you’ll need to create a new secret. ## Step 4: Configure API permissions [Section titled “Step 4: Configure API permissions”](#step-4-configure-api-permissions) 1. Navigate to **API permissions** 2. Click **Add a permission** 3. Select **Microsoft Graph > Delegated permissions** 4. Add the following permissions: * `Files.ReadWrite.All` — read and write access to all files the user can access * `offline_access` — allows Errand to refresh tokens without user interaction 5. If you are an admin, click **Grant admin consent for \[your org]** to pre-approve the permissions. Otherwise, each user will be prompted to consent during the OAuth flow. ## Step 5: Configure Errand [Section titled “Step 5: Configure Errand”](#step-5-configure-errand) Provide the OAuth credentials as environment variables to the Errand server. ### Docker Compose [Section titled “Docker Compose”](#docker-compose) Add to your `.env` file: ```bash MICROSOFT_CLIENT_ID=your-application-client-id MICROSOFT_CLIENT_SECRET=your-client-secret-value MICROSOFT_TENANT_ID=your-directory-tenant-id ``` These are already wired into the `errand` service in `docker-compose.yml`. If you used a multi-tenant configuration, you can set `MICROSOFT_TENANT_ID=common`. ### Kubernetes (Helm) [Section titled “Kubernetes (Helm)”](#kubernetes-helm) Create a Kubernetes secret: ```bash kubectl create secret generic errand-onedrive-oauth \ --from-literal=MICROSOFT_CLIENT_ID="your-application-client-id" \ --from-literal=MICROSOFT_CLIENT_SECRET="your-client-secret-value" \ --from-literal=MICROSOFT_TENANT_ID="your-directory-tenant-id" \ -n errand ``` Set the secret name in your Helm values: ```yaml onedrive: enabled: true existingSecret: errand-onedrive-oauth ``` ## Step 6: Connect your account [Section titled “Step 6: Connect your account”](#step-6-connect-your-account) 1. Open the Errand UI and navigate to **Settings > Integrations** 2. The **OneDrive** card should show a **Connect** button (if it’s greyed out, check that the environment variables are set and the MCP server is running) 3. Click **Connect** — you’ll be redirected to Microsoft’s sign-in page 4. Sign in and grant the requested permissions 5. You’ll be redirected back to Errand — the card should now show your connected account ## How it works [Section titled “How it works”](#how-it-works) Once connected: * The worker loads your OneDrive credentials before each task execution * If the OAuth access token has expired, the worker automatically refreshes it using the stored refresh token * The OneDrive MCP server is injected into the task-runner’s MCP configuration with a fresh Bearer token * The task-runner agent can use the MCP tools to interact with your OneDrive files * Cloud storage instructions are appended to the system prompt to guide the agent ## Task profile control [Section titled “Task profile control”](#task-profile-control) Cloud storage MCP servers participate in [task profile](/docs/task-profiles) filtering. If a profile specifies an `mcp_servers` list, the OneDrive server (`onedrive`) must be included for agents using that profile to access OneDrive files. Profiles with no `mcp_servers` filter include all available MCP servers by default. ## Disconnecting [Section titled “Disconnecting”](#disconnecting) To disconnect your OneDrive account: 1. Go to **Settings > Integrations** 2. Click **Disconnect** on the OneDrive card 3. The stored credentials are deleted from Errand You can also revoke access from Microsoft’s side at [account.microsoft.com/consent](https://account.microsoft.com/consent). ## Client secret expiry [Section titled “Client secret expiry”](#client-secret-expiry) Microsoft Entra client secrets have an expiry date (maximum 2 years). When the secret expires: * Existing connected users continue to work (refresh tokens don’t depend on the client secret for token refresh in some flows, but new connections will fail) * Create a new client secret in the Entra admin center and update the `MICROSOFT_CLIENT_SECRET` environment variable * No user action is needed — existing refresh tokens remain valid ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | --------------------------------------------- | --------------------------------------------------------------------------------------------------------- | | Card is greyed out | Check that `MICROSOFT_CLIENT_ID`, `MICROSOFT_CLIENT_SECRET`, and `ONEDRIVE_MCP_URL` are all set | | ”Provider not configured” error on Connect | The OAuth client credentials are not set in the server’s environment | | ”AADSTS50011: reply URL does not match” error | The redirect URI in Entra doesn’t match exactly — check for trailing slashes and protocol (http vs https) | | “Need admin approval” during consent | An admin must grant consent in the Entra portal, or the user must have permission to consent to apps | | Token refresh fails after some time | The user may have revoked access or the refresh token expired — disconnect and reconnect | | Agent reports auth errors during task | The access token may have expired mid-task (tasks longer than 1 hour) — this is a known limitation | --- # Shared Workspace > Mount a live Google Drive, OneDrive, or local folder into task runners at /shared so agents exchange files with plain filesystem operations. The **Shared Workspace** gives opted-in task runners a `/shared` folder that is a **live view of a designated Google Drive or OneDrive folder** (or, on Errand Desktop, a local directory). Agents read, edit, and write files there with ordinary filesystem operations — `cat`, an editor, `cp`, `mv` — instead of the [Google Drive](/docs/integrations/google-drive/) or [OneDrive](/docs/integrations/one-drive/) API tools. It exists because filesystem operations are the one interface that even small, local language models handle reliably. The API-based integrations remain the right choice for sharing, search, metadata, and Google-native documents; the Shared Workspace is for **bulk file read/modify/write** where agents otherwise struggle. Humans can edit the same folder at the same time (from the provider’s web UI or a desktop sync client); changes become visible to running tasks after a short polling delay. This deliberately breaks the ephemeral-task-runner guarantee — read this first Errand task runners are normally **ephemeral and isolated**: each task gets a throw-away container with no shared or persistent filesystem. The Shared Workspace **intentionally relaxes that guarantee** for the profiles you opt in. Before enabling it, understand the trade-offs: * **Persistence & cross-task visibility.** Files written by one task persist and are visible to *every other task and user* that mounts the same folder (or subpath). A task is no longer sealed off from the outside world. * **Prompt-injection blast radius.** A task that is manipulated by malicious content can **read, overwrite, delete, or exfiltrate everything in the mounted folder**. Never mount a folder that contains anything you would not want an agent to touch. * **No file locking.** Concurrent edits are **last-write-wins** — a task can clobber a human’s edit (and vice versa). Recovery relies on the cloud provider’s version history. * **Mount a dedicated folder, never the Drive/OneDrive root.** Scope exposure deliberately, and use per-profile [subpaths](#enable-it-per-task-profile) to confine each profile to a subdirectory. * **NFSv3 has no authentication.** On Kubernetes the workspace is only as private as its `NetworkPolicy`; keep it enabled. Everything **not** opted in keeps the normal ephemeral, isolated behaviour. The feature is **off by default** and enabled per [task profile](/docs/configuration/task-profiles/). ## How it works [Section titled “How it works”](#how-it-works) An optional `errand-workspace` component runs [`rclone serve nfs`](https://rclone.org/commands/rclone_serve_nfs/) directly against your chosen cloud folder — rclone is both the NFS server and the cloud client, so the cloud folder is the source of truth (there is no second canonical copy). * Task containers that opt in mount the folder over NFS at `/shared`. * **Change polling** makes human edits in the cloud visible to running tasks without a restart. * Writes are **cached and uploaded** to the provider when the agent closes the file; a persistent cache means queued uploads survive a gateway restart. * A **token-refresher** sidecar keeps the long-running gateway authenticated by fetching fresh access tokens from Errand. * The same component serves **both providers** — only the rclone remote type (`drive` vs `onedrive`) differs. On **Errand Desktop**, no gateway is needed: your Mac’s native Google Drive / OneDrive sync client already provides a live local folder, and the desktop app mounts it straight into the container. Google-native files are not synced Google Docs, Sheets, and Slides are not real files and are **not** exposed through `/shared`. Keep using the [Google Drive integration](/docs/integrations/google-drive/) for native-document workflows. ## Setup on Kubernetes (Helm) [Section titled “Setup on Kubernetes (Helm)”](#setup-on-kubernetes-helm) The gateway ships in the Helm chart, disabled by default. Enabling it involves: authorizing an rclone remote against your cloud folder, storing it (plus a bearer credential) as Secrets, and switching on the `workspace.*` values. ### Prerequisites [Section titled “Prerequisites”](#prerequisites) * A **dedicated** Google Drive or OneDrive folder (e.g. a folder named `Errand`) — **not** the account root. * Every node that can schedule task Jobs must have an **NFS client installed** (`nfs-utils` / `mount.nfs`). The kernel module alone is not enough — the kubelet performs the mount using the host’s `mount.nfs` helper. * A free **static ClusterIP** from your cluster’s service CIDR. The kubelet mounts NFS from the node network, where cluster DNS is unavailable, so the mount targets an IP, not a DNS name. * `rclone` installed on your workstation (`brew install rclone`, or see [rclone.org/install](https://rclone.org/install/)) to authorize the remote. ### Step 1: Authorize an rclone remote [Section titled “Step 1: Authorize an rclone remote”](#step-1-authorize-an-rclone-remote) On a machine with a browser, create an rclone remote for your provider. The remote **name** you choose here must match `workspace.remote` in your Helm values (default `gdrive`). ```bash rclone config # n) New remote # name> gdrive (for OneDrive, e.g. onedrive) # Storage> drive (or: onedrive) # Leave client_id/client_secret blank for a quick start (see the tip below) # scope> 1 (full access) # Use auto config? > Yes (opens a browser to grant access) ``` Confirm it works and note the folder you will serve: ```bash rclone lsd gdrive: # lists top-level folders rclone mkdir gdrive:Errand # create the dedicated workspace folder if needed ``` Use a dedicated OAuth client for production The blank-credentials quick start uses rclone’s **shared** OAuth client, whose Google Drive API quota is shared globally and is easily exhausted under concurrent tasks. For production, create your own OAuth client (you can reuse the one from the [Google Drive integration](/docs/integrations/google-drive/#step-3-create-oauth-credentials)) and supply its `client_id` / `client_secret` during `rclone config`. This gives the gateway its own quota. ### Step 2: Create the Secrets [Section titled “Step 2: Create the Secrets”](#step-2-create-the-secrets) Store the authorized rclone config, and a bearer credential the gateway uses to fetch fresh tokens from Errand: ```bash # 1. The authorized rclone remote (must contain a key named rclone.conf) kubectl create secret generic rclone-workspace-conf \ --from-file=rclone.conf="$HOME/.config/rclone/rclone.conf" \ -n errand # 2. A random workspace bearer (NOT your mcp_api_key) kubectl create secret generic errand-workspace-bearer \ --from-literal=bearer="$(openssl rand -hex 32)" \ -n errand ``` Protect the rclone config `rclone.conf` contains a long-lived OAuth refresh token for the connected account. Treat the Secret as sensitive, restrict access to it, and rotate it if it is ever exposed. ### Step 3: Enable the workspace in Helm values [Section titled “Step 3: Enable the workspace in Helm values”](#step-3-enable-the-workspace-in-helm-values) ```yaml workspace: enabled: true provider: google_drive # google_drive | onedrive folder: Errand # the dedicated folder to serve (empty = remote root — not recommended) remote: gdrive # must match the rclone remote name from Step 1 configSecret: rclone-workspace-conf bearerSecret: errand-workspace-bearer bearerKey: bearer service: clusterIP: "10.43.200.50" # REQUIRED: a free static IP in your service CIDR port: 2049 cache: size: 5Gi # VFS cache PVC (queued uploads survive restarts) storageClass: "" # empty = cluster default taskPvcName: errand-workspace # the PVC task Jobs mount networkPolicy: enabled: true # The kubelet mounts NFS from the NODE network, so mount traffic arrives from # the node IP — not the task-runner pod IP. List your node (and/or pod) CIDRs # here, or a NetworkPolicy-enforcing CNI will block the mount and /shared will # not work. allowedCIDRs: - "10.0.0.0/8" # example — set to your cluster's node/pod CIDR ``` Apply the release. The chart renders the gateway `Deployment` (rclone + refresher sidecar), a `Service` on the static ClusterIP, the cache PVC, the NFS `PersistentVolume`/`PersistentVolumeClaim` that tasks mount, and the `NetworkPolicy`. If a required value is missing, the render fails fast with a clear message. ### Step 4: Verify [Section titled “Step 4: Verify”](#step-4-verify) Open **Settings → Shared Workspace** in the Errand UI. With the gateway healthy you’ll see the provider and folder, plus a live health readout (last successful refresh, pending uploads, auth state). Then enable it on a [task profile](#enable-it-per-task-profile) and run a task that reads and writes a file under `/shared`. ## Setup with Docker Compose (local) [Section titled “Setup with Docker Compose (local)”](#setup-with-docker-compose-local) The gateway is included behind a Compose **profile**, so a plain `docker compose up` is unchanged. To run it locally you need an authorized `rclone.conf` and a few environment variables. 1. Authorize an rclone remote (see [Step 1](#step-1-authorize-an-rclone-remote)) and copy the config next to your compose file as `rclone.conf`. 2. Add to your `.env`: ```bash WORKSPACE_ENABLED=true WORKSPACE_PROVIDER=google_drive # or onedrive WORKSPACE_REMOTE=gdrive # rclone remote name WORKSPACE_FOLDER=Errand WORKSPACE_VOLUME=workspace-shared # the NFS-backed named volume WORKSPACE_BEARER= # e.g. $(openssl rand -hex 32) WORKSPACE_RCLONE_CONF=./rclone.conf ``` 3. Start with the workspace profile enabled: ```bash docker compose -f testing/docker-compose.yml --profile workspace up --build ``` The gateway publishes its NFS port on the host so the Docker daemon can mount the `workspace-shared` volume into task containers. Note The Docker host needs an NFS client (`mount.nfs`) available for the named NFS volume to mount. ## Setup on Errand Desktop (share a local folder) [Section titled “Setup on Errand Desktop (share a local folder)”](#setup-on-errand-desktop-share-a-local-folder) On Errand Desktop the container runtime can mount a **local host directory** straight into the task container at `/shared` — no gateway, rclone remote, or cloud credentials required. Because it is just a local folder, this is the simplest way to use the Shared Workspace. The most useful pattern is to point it at the **local sync folder of your existing Google Drive or OneDrive client**, so the same files are available to agents, to you in Finder, and in the cloud: * Google Drive for desktop: e.g. `~/Library/CloudStorage/GoogleDrive-/My Drive/Errand` * OneDrive: e.g. `~/Library/CloudStorage/OneDrive-/Errand` * Or any plain local directory you create, e.g. `~/ErrandWorkspace`. Configure the folder as the approved workspace directory in the Errand Desktop app; the app mounts it (or the profile’s subpath within it) at `/shared` and rejects any path outside the approved directory. macOS “mirror” mode is required for cloud sync folders Google Drive and OneDrive on macOS default to **File Provider** streaming, where files are online-only placeholders that are downloaded on demand. Those placeholders do **not** materialize reliably through the container share, so agents may see empty or missing files. Set the shared folder to **“Mirror files”** (Google Drive: Preferences → *Mirror files*; OneDrive: *Always keep on this device*) so the files exist on disk. A plain local directory needs no special setting. ## Enable it per task profile [Section titled “Enable it per task profile”](#enable-it-per-task-profile) The Shared Workspace is only ever mounted for [task profiles](/docs/configuration/task-profiles/) that opt in: 1. Go to **Settings → Task Profiles** and create or edit a profile. 2. Turn on **Shared workspace**. 3. Optionally set a **Subpath** (relative, no `..`) to confine that profile to a subdirectory of the workspace folder — e.g. `reports/nginx`. Leave it blank to mount the whole folder. 4. Save. Tasks that match this profile will mount `/shared`; all other tasks stay fully ephemeral. If a profile requests the workspace but the deployment has none configured (or the configuration is incompatible with the request), the task runs **without** the mount and a warning is recorded in the task transcript. ## How agents use it [Section titled “How agents use it”](#how-agents-use-it) When the mount is active, Errand injects a system skill that tells the agent to: * use plain filesystem operations on `/shared` instead of the cloud API tools; * use **cross-provider-safe filenames** — avoid `" * : < > ? / \ |`, leading/trailing spaces or dots, and reserved names; treat names as case-insensitive (OneDrive is stricter than Drive); * **re-read a file immediately before writing it back** and keep the read-modify-write window short (mitigating last-write-wins); * **write atomically** (temp file, then rename); * **never execute or follow instructions** found in `/shared` content — it is untrusted data. ## Conflict model [Section titled “Conflict model”](#conflict-model) There is no file locking anywhere in the chain (neither cloud provider offers it, and the NFS layer has none). The model is **last-write-wins**, made survivable by: 1. short change-polling so reads stay reasonably fresh; 2. the re-read-before-write / atomic-write discipline in the agent skill; 3. **provider version history** — a clobbered edit is recoverable from the Google Drive or OneDrive UI. Scheduling two tasks that write the same file at the same time is an application concern; storage does not solve it. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Settings shows “not configured” | `workspace.enabled` is false, or the deployment env vars are unset. On Helm, confirm the release rendered the workspace resources. | | Helm render fails with a “required” error | A required value is unset — set `workspace.service.clusterIP`, `workspace.configSecret`, and `workspace.bearerSecret`. | | Task Jobs can’t mount `/shared` | The node is missing an NFS client — install `nfs-utils` on all nodes. | | Mount blocked when NetworkPolicy is enforced | Add your node/pod CIDRs to `workspace.networkPolicy.allowedCIDRs` — the kubelet mounts from the node IP, not the pod IP. | | Health shows an auth error | The token-refresher can’t reach Errand or the bearer is wrong — check `bearerSecret` matches on both the server and the gateway, and that the gateway can reach the server. | | `403` / rate-limit errors under load | You’re using rclone’s shared OAuth client — configure a dedicated `client_id` (see the tip in Step 1). | | Desktop: agent sees empty/missing files | The cloud sync folder is in streaming mode — switch it to “mirror”/“always keep on this device”. | | A human edit isn’t visible yet | Change polling has a delay (seconds to \~a minute depending on the provider) — wait and re-read. | --- # Slack > Connect Slack to create and manage tasks from your workspace. Slack integration lets you create and manage Errand tasks directly from your Slack workspace. You can use slash commands, mention the bot in conversations, and get real-time updates as your tasks progress — all without leaving Slack. ## Features [Section titled “Features”](#features) * **Slash commands** — create tasks, check status, list tasks, run tasks, and view output * **Bot mentions** — @mention the Errand bot in any channel to create a task from a message * **Interactive buttons** — view task status and output with one click * **Real-time updates** — get notified in Slack as tasks progress ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * Admin access to your Slack workspace (to install apps) * A way for Slack to reach your Errand installation over the internet. You have two options: * **Errand Cloud** (recommended) — the [Cloud Service](/docs/cloud-service) acts as a webhook relay, receiving Slack events on your behalf and forwarding them to your local installation. No networking changes needed on your end. * **Self-managed** — if you prefer not to use Errand Cloud, you’ll need to expose your Errand server to the internet yourself (e.g. via port forwarding, a reverse proxy, or a VPN tunnel) so that Slack can deliver webhooks directly to it. You are responsible for securing this connection with HTTPS. ## Step 1: Create a Slack App [Section titled “Step 1: Create a Slack App”](#step-1-create-a-slack-app) 1. Go to [api.slack.com/apps](https://api.slack.com/apps) 2. Click **Create New App** 3. Choose **From scratch** 4. Give your app a name (e.g. “Errand”) and select your workspace 5. Click **Create App** ## Step 2: Configure bot token scopes [Section titled “Step 2: Configure bot token scopes”](#step-2-configure-bot-token-scopes) 1. In the left sidebar, navigate to **OAuth & Permissions** 2. Scroll down to **Scopes > Bot Token Scopes** 3. Add the following scopes: * `app_mentions:read` - allows the bot to view messages that mention it * `chat:write` — allows the bot to send messages * `chat:write.customize` - allows the bot to send messages with custom usernames and icons * `commands` — enables slash commands * `users:read` — resolve user IDs to profile information * `users:read.email` — resolve Slack users to email addresses for audit trail ## Step 3: Install the app to your workspace [Section titled “Step 3: Install the app to your workspace”](#step-3-install-the-app-to-your-workspace) 1. Go to **OAuth & Permissions** in the left sidebar 2. Click **Install to Workspace** 3. Review the permissions and click **Allow** 4. Copy the **Bot User OAuth Token** (it starts with `xoxb-`) — you’ll need this in a later step ## Step 4: Get the Signing Secret [Section titled “Step 4: Get the Signing Secret”](#step-4-get-the-signing-secret) 1. In the left sidebar, go to **Basic Information** 2. Scroll to **App Credentials** 3. Click **Show** next to **Signing Secret** and copy the value ## Step 5: Enter credentials in Errand [Section titled “Step 5: Enter credentials in Errand”](#step-5-enter-credentials-in-errand) 1. Open the Errand UI and go to **Settings > Integrations** 2. Find the **Slack** card and click it 3. Enter the **Bot Token** (`xoxb-...`) from Step 3 4. Enter the **Signing Secret** from Step 4 5. Click **Test & Save** — Errand will verify the credentials against the Slack API ## Step 6: Configure webhook URLs [Section titled “Step 6: Configure webhook URLs”](#step-6-configure-webhook-urls) Because Errand runs locally on your machine, Slack can’t send events directly to it. Instead, Errand Cloud acts as a relay. 1. In Errand, go to **Settings > Cloud Service** to find your cloud endpoint URLs for: * **Events** — used for Event Subscriptions * **Commands** — used for Slash Commands * **Interactivity** — used for Interactive Components 2. Copy each URL into the corresponding section of your Slack app (see Steps 7 and 8 below) ## Step 7: Enable Event Subscriptions [Section titled “Step 7: Enable Event Subscriptions”](#step-7-enable-event-subscriptions) 1. In your Slack app settings, go to **Event Subscriptions** 2. Toggle **Enable Events** to **On** 3. Paste the **Events** webhook URL from Step 6 into the **Request URL** field 4. Under **Subscribe to bot events**, click **Add Bot User Event** and add: * `app_mention` 5. Click **Save Changes** ## Step 8: Create the slash command [Section titled “Step 8: Create the slash command”](#step-8-create-the-slash-command) 1. In your Slack app settings, go to **Slash Commands** 2. Click **Create New Command** 3. Configure: * **Command**: `/task` * **Request URL**: paste the **Commands** webhook URL from Step 6 * **Short Description**: e.g. “Create and manage Errand tasks” * **Usage Hint**: `new | list [status] | status <id> | output <id>` 4. Click **Save** ## Using Slack with Errand [Section titled “Using Slack with Errand”](#using-slack-with-errand) Once everything is set up, you can interact with Errand directly from Slack: * **Create a task**: Type `/task new <description>` in any channel * **Check task status**: Type `/task status` to see your current task * **List tasks**: Type `/task list` to see recent tasks * **View output**: Type `/task output` to see the result of a completed task * **Mention the bot**: Type `@Errand <your request>` in any channel to create a task from your message Tasks created from Slack are automatically tagged with `slack` so you can easily find them later. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | ---------------------------------- | ---------------------------------------------------------------------------------------- | | Bot not responding to messages | Check that your Errand Cloud connection is active in **Settings > Cloud Service** | | Slash command returns an error | Verify the **Commands** webhook URL is correct in your Slack app settings | | Messages not updating in real time | Check that **Event Subscriptions** are enabled and the `app_mention` event is subscribed | | ”not\_authed” error | Regenerate the Bot Token in your Slack app and update it in Errand | --- # Twitter > Connect Twitter/X to allow agents to post tweets. Twitter/X integration allows Errand agents to post tweets on your behalf during task execution. When connected, an agent can compose and publish tweets as part of completing a task. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * An X/Twitter Developer account ([developer.x.com](https://developer.x.com)) * A Developer App with **Read and Write** permissions ## Step 1: Create or configure your X Developer App [Section titled “Step 1: Create or configure your X Developer App”](#step-1-create-or-configure-your-x-developer-app) 1. Go to the [X Developer Portal](https://developer.x.com) 2. Navigate to your **Projects & Apps** dashboard 3. Create a new app or select an existing one ## Step 2: Set app permissions [Section titled “Step 2: Set app permissions”](#step-2-set-app-permissions) 1. In your app settings, go to **User authentication settings** 2. Set **App permissions** to **Read and Write** 3. Save your changes Caution If you change permissions on an existing app, you must regenerate your Access Token and Secret for the new permissions to take effect. ## Step 3: Generate API credentials [Section titled “Step 3: Generate API credentials”](#step-3-generate-api-credentials) 1. In your app settings, navigate to **Keys and Tokens** 2. Generate (or regenerate) the following credentials: * **API Key** (also called Consumer Key) * **API Secret** (also called Consumer Secret) * **Access Token** * **Access Token Secret** 3. Copy all four values immediately — some are only shown once ## Step 4: Enter credentials in Errand [Section titled “Step 4: Enter credentials in Errand”](#step-4-enter-credentials-in-errand) 1. Open the Errand UI and go to **Settings > Integrations** 2. Find the **Twitter/X** card and click it 3. Enter all four credentials: * API Key * API Secret * Access Token * Access Token Secret 4. Click **Test & Save** Errand verifies the credentials against the Twitter API before saving. If verification fails, double-check that you copied the values correctly and that your app has Read and Write permissions. ## How it works [Section titled “How it works”](#how-it-works) * When an agent needs to post a tweet during task execution, it uses your stored credentials to publish via the X API * All credentials are encrypted at rest using your Errand credential encryption key * Tasks that use Twitter are automatically tagged with `media` and `post` ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | ”Invalid credentials” error on save | Regenerate your keys and tokens in the X Developer Portal and re-enter them | | ”Read-only” or “Forbidden” error | Your app permissions are set to Read only — change to **Read and Write** and regenerate tokens | | Tweet fails with rate limit error | The X API enforces posting limits — wait and try again, or check your app’s rate limit status in the Developer Portal | | Credentials not saving | Ensure all four fields (API Key, API Secret, Access Token, Access Token Secret) are filled in | --- # Web Search > Enable web search capabilities for task agents. Web search gives agents the ability to search the internet during task execution. This is useful for tasks that need up-to-date information, research, fact-checking, or any work that benefits from live web results. ## How it works [Section titled “How it works”](#how-it-works) Web search is powered by [SearXNG](https://docs.searxng.org/), a privacy-respecting metasearch engine. SearXNG aggregates results from multiple search engines without tracking your queries. By default, Errand uses a hosted instance at `https://search.errand.cloud` — this works out of the box with no setup required. ## Configuration [Section titled “Configuration”](#configuration) If you want to use a self-hosted SearXNG instance (for privacy, performance, or customization), you can change the instance URL: 1. Open the Errand UI and go to **Settings > Integrations** 2. Find the **SearXNG Search** card and click it 3. Configure: | Field | Description | Default | | ---------------- | ------------------------------------------------ | ----------------------------- | | **Instance URL** | The SearXNG server address | `https://search.errand.cloud` | | **Username** | Optional — for private instances with basic auth | — | | **Password** | Optional — for private instances with basic auth | — | 4. Click **Test & Save** to verify the connection ## No setup needed for default instance [Section titled “No setup needed for default instance”](#no-setup-needed-for-default-instance) If you’re happy using the hosted instance at `https://search.errand.cloud`, there’s nothing to configure. Web search is available to agents immediately. ## What agents can do with web search [Section titled “What agents can do with web search”](#what-agents-can-do-with-web-search) During task execution, agents can: * **Search by keyword** with category filters (general, news, images, etc.) * **Filter by time range** to find recent or older results * **Select language** for localized results * **Control safe search** settings * **Browse paginated results** for deeper research Each search result includes a URL, title, and content snippet that the agent can use to complete your task. ## Self-hosting SearXNG [Section titled “Self-hosting SearXNG”](#self-hosting-searxng) If you prefer to run your own SearXNG instance: 1. Follow the [SearXNG installation guide](https://docs.searxng.org/admin/installation.html) 2. Ensure the JSON search format is enabled in your SearXNG settings 3. Update the **Instance URL** in Errand to point to your instance ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Issue | Solution | | ----------------------- | ------------------------------------------------------------------------------------------ | | Search returns an error | Check that the **Instance URL** is correct and the SearXNG instance is running | | Slow search results | The default hosted instance may be under load — consider running your own SearXNG instance | | No results returned | Try adjusting the search query — very specific or unusual terms may not return results | | Authentication error | If using a private instance with basic auth, verify the username and password | --- # Introduction to Errand AI Task Automation > Get started with Errand AI — learn how to delegate tasks to AI agents using natural language on your own self-hosted infrastructure. Errand AI is a personal task automation platform. You describe what you need done in plain language, and an AI agent takes care of it — researching topics, drafting emails, browsing the web, managing files, interacting with APIs, and much more. It runs on your own hardware, keeping your data under your control. ![Errand task board showing tasks across Pending, Running, Completed, and Review columns](/_astro/task-board.B-VJcucp_ZbDenY.webp) ## How It Works [Section titled “How It Works”](#how-it-works) You give Errand a task. An AI agent picks it up, works through it step by step in an isolated container, and delivers the result. You can watch the agent’s progress in real time, answer follow-up questions if it needs clarification, and schedule tasks to run later or on a repeating basis. Behind the scenes, Errand is a task scheduler with AI workers. Tasks flow through a simple lifecycle: **Pending** → **Running** → **Completed** (or **Review** if the agent needs your input) Each task runs in its own ephemeral sandbox — a fresh container that is created for the task and destroyed when it is done. There is no shared state between tasks, no persistent sessions, and no way for one task to interfere with another. You control exactly which tools and integrations each task can access. ## Many Ways to Create Tasks [Section titled “Many Ways to Create Tasks”](#many-ways-to-create-tasks) One of Errand’s strengths is that you are not limited to a single interface. Tasks can come from anywhere: ### Web UI [Section titled “Web UI”](#web-ui) The task board is the primary interface for most users. Create tasks by typing a description, or use **voice transcription** to speak your task and have it converted to text automatically. The board gives you a visual overview of all your tasks across their lifecycle stages, with real-time streaming of the agent’s reasoning and tool usage as it works. ### Slack [Section titled “Slack”](#slack) With the [Slack integration](/docs/docs/integrations/slack/), you can create and manage tasks without leaving your workspace. Use `/task new research competitor pricing` to fire off a task, `@mention` the Errand bot in a channel to turn a conversation into a task, or check on progress with `/task status`. Results are delivered back to Slack as they complete. ### MCP Server [Section titled “MCP Server”](#mcp-server) Errand exposes a [Model Context Protocol server](/docs/docs/mcp-server/) that any AI-capable tool can connect to. This is what makes Errand **AI-native** — not just a tool for humans to manage AI, but a platform that other AI agents can use too. Connect your IDE (Claude Code, Cursor, Windsurf) or any MCP-compatible agent to Errand’s `/mcp/` endpoint, and it can create tasks, check status, read results, and orchestrate multi-step workflows programmatically. Your coding assistant can delegate long-running research to Errand while you keep working, or a custom agent can use Errand as its task execution backend. ### Agents Creating Tasks [Section titled “Agents Creating Tasks”](#agents-creating-tasks) When an Errand agent is working on a task, it can create new tasks itself using the built-in `new_task` tool. This enables delegation chains — a complex task can spawn sub-tasks that run in parallel, each in their own isolated container. The originating agent can check on progress and combine the results. ## What Can It Do? [Section titled “What Can It Do?”](#what-can-it-do) Errand agents have access to a configurable set of tools through MCP servers. Out of the box, agents can: * **Search the web** and synthesize information from multiple sources * **Send, read, and manage emails** through your connected email account * **Browse websites** using a full headless browser with Playwright * **Access cloud files** from Google Drive and OneDrive * **Interact with GitHub** — read repositories, create issues, review code * **Post to social media** and manage communications * **Remember context** across tasks using persistent AI memory You can extend this further by adding your own MCP servers or connecting additional integrations. ## Runs on Your Hardware [Section titled “Runs on Your Hardware”](#runs-on-your-hardware) Errand is designed to run on infrastructure you control: * A **Mac** using the [Errand Desktop](/docs/docs/installation/macos/) app (the simplest option — one download and you’re running) * A **home server** or personal computer using [Docker Compose](/docs/docs/installation/docker/) * A **Kubernetes cluster** for team deployments with [Helm charts](/docs/docs/installation/kubernetes/) Container images are available for both x86\_64 and ARM64, so Errand runs on everything from a Raspberry Pi to a multi-node production cluster. Your tasks, credentials, and data stay on your machine. Nothing is sent to external services unless you explicitly configure an integration that requires it (like connecting an email account or an LLM provider). ## Remote Access [Section titled “Remote Access”](#remote-access) Since Errand runs locally, it’s only accessible from your network by default. The optional [Errand Cloud](/docs/docs/cloud-service/) subscription gives you secure remote access from anywhere, plus webhook relay for integrations like Slack that need a public endpoint. Your data passes through but is never stored on the cloud service. ## Next Steps [Section titled “Next Steps”](#next-steps) * **Install Errand** — Get started with [macOS](/docs/docs/installation/macos/), [Docker](/docs/docs/installation/docker/), or [Kubernetes](/docs/docs/installation/kubernetes/) * **Configure your AI model** — Connect to an [LLM provider](/docs/docs/ai-models/) * **Set up integrations** — Connect [email](/docs/docs/integrations/email/), [Slack](/docs/docs/integrations/slack/), [GitHub](/docs/docs/integrations/github/), and more * **Understand the architecture** — See how the [components fit together](/docs/docs/architecture/overview/) --- # MCP Server > Errand's built-in Model Context Protocol server for agent tools. Errand includes a built-in **MCP (Model Context Protocol) server** that gives AI agents access to tools while they work on your tasks. Think of it as a toolkit that agents can reach into whenever they need to do something — like searching the web, sending an email, or creating a new task. ## What is MCP? [Section titled “What is MCP?”](#what-is-mcp) MCP is an open standard for connecting AI models to external tools and data sources. It provides a consistent way for agents to discover and use tools, no matter where those tools come from. You don’t need to understand the technical details — just know that it is what allows your agents to do useful things beyond generating text. ## The Built-in Server [Section titled “The Built-in Server”](#the-built-in-server) Errand’s MCP server runs automatically as part of your installation at the `/mcp/` endpoint. There’s nothing extra to install or configure — it is ready to go out of the box. ### Authentication [Section titled “Authentication”](#authentication) The MCP server is secured with a **Bearer token** to prevent unauthorised access. This token is auto-generated the first time Errand starts up. To view your token: 1. Go to **Settings > Security** 2. Look for the **MCP API Key** field Keep this key safe — anyone with this token can access your agent tools. ## Built-in Tools [Section titled “Built-in Tools”](#built-in-tools) The following tools are available to agents by default: | Tool | Description | | -------------------- | --------------------------------------------------- | | `new_task` | Create a new task from within a running task | | `task_status` | Check the status and output of another task | | `list_tasks` | List tasks, optionally filtered by status | | `web_search` | Search the web via SearXNG | | `list_emails` | List emails from connected email account | | `read_email` | Read the full content of an email | | `send_email` | Send an email (restricted to authorised recipients) | | `move_email` | Move an email between folders | | `forward_email` | Forward an email | | `list_email_folders` | List available email folders | Agents automatically choose the right tool for the job based on what your task requires. For example, if you ask Errand to “check my inbox and summarise new emails,” the agent will use `list_emails` and `read_email` behind the scenes. ## Adding More MCP Servers [Section titled “Adding More MCP Servers”](#adding-more-mcp-servers) You can extend what your agents can do by registering additional MCP servers. This lets you connect custom tools or third-party services. To add a new MCP server: 1. Go to **Settings > Agent Configuration** 2. Scroll to the **MCP Server Configuration** section 3. Add your server details Once registered, the tools from that server become available to your agents alongside the built-in ones. ## Controlling Tool Access with Task Profiles [Section titled “Controlling Tool Access with Task Profiles”](#controlling-tool-access-with-task-profiles) Not every task needs access to every tool. **Task profiles** let you control which MCP servers (and therefore which tools) are available for different types of tasks. For example, you might want a “research” profile that only has web search, or an “email” profile that includes email tools but not task management. ## Using Errand’s MCP Server from Other Clients [Section titled “Using Errand’s MCP Server from Other Clients”](#using-errands-mcp-server-from-other-clients) The MCP server isn’t just for Errand’s own agents. You can point any MCP-compatible client at your Errand installation to use these tools externally. This means other AI applications or agents on your network can tap into Errand’s capabilities — like sending emails or managing tasks — through the same standard protocol. To connect an external client, you’ll need: * Your Errand server’s address (e.g., `http://your-server:port/mcp/`) * Your MCP API Key (found in **Settings > Security**) --- # Privacy Policy Last updated: 13 March 2026 This Privacy Policy explains how Errand AI (“Errand”, “we”, “us”) collects, uses, and shares information when you: * Visit our website and documentation (this site) * Use Errand software you run on your own hardware (for example, the desktop app or self-hosted deployment) * Use optional cloud features and integrations (for example, remote access, webhook relay, Slack, email, and third-party model providers) If you are using Errand through an organization, your organization may have additional policies that apply. ## Summary [Section titled “Summary”](#summary) * **Errand is designed to run on your hardware.** Many tasks and results can stay local. * **Integrations are optional.** If you connect third-party services (like Slack, email, GitHub, or a model provider), data you choose to send will be shared with those providers to perform the requested functionality. * **We aim to collect the minimum.** Website and cloud features typically require some operational data (for example, account or billing information) to work. ## Information we collect [Section titled “Information we collect”](#information-we-collect) The categories of information we collect depend on how you use Errand. ### A. Website and documentation [Section titled “A. Website and documentation”](#a-website-and-documentation) When you access this site, we (or our service providers) may collect: * **Device and usage data** (such as IP address, user agent, pages viewed, approximate location derived from IP, and timestamps) * **Cookie or similar identifiers** used for essential site functionality and (if enabled) analytics * **Support and communications** if you contact us (your email address, message content, and any information you include) ### B. Errand software running on your hardware [Section titled “B. Errand software running on your hardware”](#b-errand-software-running-on-your-hardware) Errand is designed so that tasks can be executed locally. Depending on your configuration, information may be processed on your machine such as: * **Task content** you create (prompts/instructions, attachments, and related metadata) * **Task outputs** generated by the system * **Configuration data** (settings, enabled tools, integration configuration) * **Credentials and secrets** you provide for integrations (stored locally and/or encrypted, depending on your setup) Whether any of this is transmitted off-device depends on what you enable (for example, calling a third-party LLM API or sending a message to Slack). ### C. Optional cloud features (Errand Cloud) and hosted services [Section titled “C. Optional cloud features (Errand Cloud) and hosted services”](#c-optional-cloud-features-errand-cloud-and-hosted-services) If you use optional hosted features, we may collect and process: * **Account information** (such as name, email address, organization/tenant identifiers) * **Authentication and security data** (login timestamps, token identifiers, and audit/security logs) * **Operational telemetry** (service performance metrics, error logs, and request metadata) * **Billing information** (for example, subscription status and payment-related identifiers). Payment card details are typically handled by a payment processor rather than stored by us. ### D. Third-party integrations [Section titled “D. Third-party integrations”](#d-third-party-integrations) If you connect third-party integrations, we may receive information from, and send information to, those services as needed to provide the integration. For example: * Slack messages or channel metadata (if you install the Slack integration) * Email headers and message content (if you connect an email account) * Repository and issue content (if you connect GitHub) * Files and metadata (if you connect Google Drive or OneDrive) The data involved depends on what you authorize and the actions you request. ## How we use information [Section titled “How we use information”](#how-we-use-information) We use information to: * Provide, maintain, and improve Errand and related services * Authenticate users and secure the service (prevent fraud, abuse, and unauthorized access) * Provide support, respond to requests, and communicate with you * Process subscriptions and manage billing * Monitor reliability, debug issues, and perform analytics (where enabled) * Comply with legal obligations and enforce our terms ## How we share information [Section titled “How we share information”](#how-we-share-information) We may share information in the following circumstances: * **With service providers** that help us operate the website and services (for example hosting, analytics, customer support, and payment processing). They are authorized to use information only as necessary to provide services to us. * **With third-party integrations you enable.** If you connect a provider (such as Slack, email, GitHub, or a model provider), we share the information needed to perform the actions you request. * **For legal and safety reasons** if we believe disclosure is necessary to comply with law, protect rights and safety, investigate fraud, or respond to lawful requests. * **Business transfers** in connection with a merger, acquisition, financing, or sale of assets (subject to appropriate safeguards). We do not sell personal information in the ordinary sense of “selling” under many privacy laws. ## Cookies and analytics [Section titled “Cookies and analytics”](#cookies-and-analytics) We may use cookies or similar technologies for: * **Essential functionality** (for example, security, session management, and preferences) * **Analytics** to understand site usage and improve content (if enabled) If you prefer not to accept cookies, you can typically adjust your browser settings. Some site features may not function properly without essential cookies. ## Data retention [Section titled “Data retention”](#data-retention) We retain information only as long as reasonably necessary for the purposes described in this policy, including: * Providing the services you request * Meeting legal, accounting, or reporting requirements * Resolving disputes and enforcing agreements Retention periods vary depending on the type of information, how it is used, and our legal obligations. ## Security [Section titled “Security”](#security) We use administrative, technical, and organizational measures designed to protect information. No method of transmission or storage is 100% secure, and we cannot guarantee absolute security. ## International data transfers [Section titled “International data transfers”](#international-data-transfers) If you access Errand from outside the country where our service providers operate, your information may be transferred, stored, or processed in other countries. Where required, we use appropriate safeguards for cross-border transfers. ## Your choices and rights [Section titled “Your choices and rights”](#your-choices-and-rights) Depending on where you live, you may have rights such as: * Accessing, correcting, or deleting personal information * Objecting to or restricting certain processing * Portability (receiving a copy of certain information) * Withdrawing consent where processing is based on consent To make a request, contact us using the information in the **Contact us** section. We may need to verify your identity before fulfilling certain requests. ## Children’s privacy [Section titled “Children’s privacy”](#childrens-privacy) Errand is not intended for children, and we do not knowingly collect personal information from children. If you believe a child has provided personal information, contact us and we will take appropriate steps. ## Changes to this policy [Section titled “Changes to this policy”](#changes-to-this-policy) We may update this policy from time to time. We will update the “Last updated” date above and, if changes are material, we may provide additional notice. ## Contact us [Section titled “Contact us”](#contact-us) Questions or requests about privacy: * Email: **<rob.coward@devops-consultants.co.uk>**