Downcity
PluginsBuilt-in Plugins

auth Plugin

A detailed guide to the auth built-in plugin, including its authorization flow, role resolution model, available actions, and how it uses guard, effect, and resolve points

auth Plugin

auth is the most platform-rule-oriented built-in plugin in Downcity today.

It is not mainly there to add a user-facing business feature. It answers three foundation questions:

  • who is allowed to enter the chat pipeline
  • which users and chats has the platform already observed
  • what is the effective role of one user right now

What it does

auth is responsible for four main jobs:

  1. check authorization on inbound chat traffic
  2. record observed users and chat principals
  3. resolve a user's effective role in one channel
  4. expose authorization config and snapshots through actions

So it spans:

  • entry guarding
  • runtime observation
  • permission resolution
  • control-plane actions

Why it is a special plugin

Unlike most other built-in plugins, auth is not treated like a normal optional plugin.

Its availability semantics are currently:

  • enabled: true
  • available: true

In practice, it is always treated as usable.

That design makes sense because once authorization becomes a fully optional capability that can disappear like any other utility plugin, the platform rule layer becomes unstable.

Which plugin capabilities it uses

auth uses:

  • availability
  • hooks.guard
  • hooks.effect
  • resolves
  • actions

It does not use:

  • setup
  • usage
  • system
  • http.runtime

That tells you auth is not a UI-installable dependency plugin, and it is not mainly driven by prompt injection.

Typical runtime flow

When a normal chat message enters the system, auth usually participates in this order:

  1. the chat inbound flow reaches an authorization point
  2. the guard hook evaluates the incoming channel, chatId, userId, and related fields
  3. if authorization fails, the pipeline stops immediately
  4. if authorization passes, the rest of the message flow continues
  5. a later observation point uses effect to record observed user or chat data
  6. whenever downstream logic needs the user's role, it calls the resolve point

In short:

  • guard decides whether the message can enter
  • effect records what was observed
  • resolve answers the role question

Typical scenarios

Scenario 1: only allow specific Telegram users to talk to the agent

You can write authorization rules into auth, and every inbound Telegram message will pass through the guard check first.

If a user is not allowed, the message never reaches the later agent execution stages.

Scenario 2: after connecting one group chat, you want to inspect what principals the system has already seen

Call the snapshot action and inspect:

  • recorded users
  • recorded chats
  • the currently effective authorization config

Scenario 3: downstream capability policy depends on user roles

For example:

  • admins may use high-risk tools
  • regular members may only run read-only tasks

In that case, downstream logic can use the resolve point instead of duplicating authorization-store reads.

How to register it in the SDK

import { Agent, authPlugin } from "@downcity/agent";

const agent = new Agent({
  id: "chat-agent",
  path: "/path/to/project",
  tools: {},
  plugins: [authPlugin],
});

auth is more often consumed automatically by runtime integration points than manually called like a business plugin.

Main actions

auth exposes four core actions.

ActionWhat it doesBest use case
snapshotread the current authorization snapshotinspect observed state and rules
readConfigread the authorization configcontrol-plane UI or debugging
writeConfigwrite authorization configbulk update policy rules
setUserRoleset one user's rolechange role assignment for one user

Read the current authorization snapshot

const snapshot = await agent.plugins.runAction({
  plugin: "auth",
  action: "snapshot",
});

This usually returns:

  • current authorization config
  • recorded users
  • recorded chats

Read the current authorization config

const config = await agent.plugins.runAction({
  plugin: "auth",
  action: "readConfig",
});

Write a new authorization config

const result = await agent.plugins.runAction({
  plugin: "auth",
  action: "writeConfig",
  payload: {
    config: {
      telegram: {
        enabled: true,
      },
    },
  },
});

Set the role for one user

const result = await agent.plugins.runAction({
  plugin: "auth",
  action: "setUserRole",
  payload: {
    channel: "telegram",
    userId: "123456",
    roleId: "admin",
  },
});

How it relates to hooks and resolve

auth is one of the clearest built-in examples for understanding these mechanisms:

  • guard: stop messages that should not enter
  • effect: record observed principals
  • resolve: return the effective user role

If those concepts still feel abstract after reading this page, continue with:

Its boundary relative to services

auth is not a long-lived connection-holding or worker-like service.

It is closer to a rule orchestration layer:

  • attach rules at important runtime points
  • expose config and state through one standard boundary
  • let other capabilities read resolved roles through a common interface

If you think of it as a service first, it becomes easy to over-couple permission checks to one long-lived runtime instance. The current design intentionally avoids that.

Important boundaries

It focuses on chat authorization and role resolution

auth is not a general-purpose ACL system or a universal resource authorization framework.

Its current focus is the chat-channel domain.

It depends on standard channel identifiers

Current channel handling expects standard values such as:

  • telegram
  • feishu
  • qq

If the channel is invalid, the relevant action or hook will fail fast.

It is not a setup-oriented plugin

You do not use setup or usage for model installation or provider switching the way you do with web, asr, or tts.

Its value is rule evaluation, not dependency installation.

When to study it first

Use auth as a reference when you want to design:

  • inbound guards
  • principal observation
  • role resolution
  • platform-rule plugins