Synaplan
Open-source AI platform for companies: self-hosted AI agents, GDPR-compliant chatbot widget, RAG knowledge base, WhatsApp and Outlook AI, MCP, multi-model routing. Docker, Kubernetes or hosted in Germ
Enroll, observe, deploy, and verify AI machines from one control plane.
BusinessGo · ShellGitHub @TED-H-comOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Evidence-first control plane that enrolls, deploys, verifies, and audits Linux machines running AI agents.
Loading the full README. The saved excerpt is shown below.
Evidence-first control for AI machines. 以證據為核心的 AI 機隊管理平臺。 AI-Intune is a focused control plane for Linux, macOS, and Windows machines running AI agents and coding tools. It gives one operator a path from enrollment to an exact software profile, execution, verification, and retained evidence. Linux is the deployed path; macOS and Windows Agent paths have repository tests and still need hardware acceptance. The Hub and Agent binaries are named clawctl-hub and clawctl-agent.Read the full README ↗
AI-Intune is a focused control plane for Linux, macOS, and Windows machines running AI agents and coding tools. It gives one operator a path from enrollment to an exact software profile, execution, verification, and retained evidence. Linux is the deployed path; macOS and Windows Agent paths have repository tests and still need hardware acceptance.
The Hub and Agent binaries are named clawctl-hub and clawctl-agent.
AI-Intune is an operating control plane, but it is not a complete Microsoft Intune replacement. The current scope includes fleet inventory, enrollment and lifecycle, app artifacts and profiles, dependency-aware jobs, deployments, reports, audit, Tailnet reconciliation, retention maintenance, and asynchronous backup restore drills. The Web console now follows workload-oriented navigation with Devices, Apps, Endpoint security, Agents, Reports, Tenant administration, and Troubleshooting + support.
The Hub registers independent verifiers in their own failure domain, accepts evidence from them on a separate credential plane, and reports that evidence as its own typed verdict on the job page. A sampleagent3 fleet-peer runner was deployed for OpenClaw verification; independent evidence is scoped to jobs it has actually checked, not every job. The pinned catalog path exists for Claude Code, Codex, Grok, Antigravity, and Linux BAT Server. A complete default profile is still missing. Ticket usage has one bounded contract across Web, CSV, the strict CLI, and GET /v1/operator/tickets. See the feature inventory for the exact delivery gaps. The first-principles review is a private working note and is not published here.
The recommended OSS deployment uses local admin accounts over public HTTPS (Autopilot). Advanced deployments can use a private Tailscale listener with capability grants; both mode supports local sessions plus direct-tailnet WhoIs under the documented listener constraints.
AI workloads fail quietly. A process can remain alive while its login has expired, its runtime is wrong, or it has stopped completing useful work. Conventional device management can report packages, processes, and disk usage; it does not define what success means for an AI agent.
AI-Intune starts from two rules:
That turns the operating question from “did the command run?” into “what proves this machine is correct?”
build Hub + Agent bundles
│
▼
install Hub on the tailnet
│
▼
create one-time enrollment ──► install Tailscale + Agent + systemd service
│ │
│ ▼
└──────── assign machine profile ◄── fresh check-in
│
▼
resolve runtimes → install app → verify
│
▼
managed + auditable
One bootstrap operation establishes everything an endpoint needs to pull managed work:
clawctl-agent binaryUser=, the
lingered user manager for managed runtime services, and the enabled job loopThe selected profile then supplies the application. An OpenClaw profile resolves the exact Node runtime first, installs OpenClaw, persists its local gateway configuration, and activates the managed service; a Hermes profile resolves the exact official multi-architecture OCI image. The endpoint verifies the selected runtime before the Hub records the assignment as complete. Assigning the other profile performs the full OpenClaw ↔ Hermes switch and restores the prior runtime if verification fails.
amd64 and arm64 bootstrap downloads with size and SHA-256machine actions, and GET /v1/operator/machines/{id}/actions┌──────────────────────── Operator plane ────────────────────────┐
│ Web console Strict CLI / API │
└───────────────────────────────┬─────────────────────────────────┘
│ Local session / Tailscale capability
▼
┌────────────────────────── clawctl-hub ─────────────────────────┐
│ inventory │ observations │ catalog │ profiles │ desired state │
│ jobs │ deployments │ receipts │ audit │ metrics │
│ SQLite ledger │
└───────────────────────────────┬─────────────────────────────────┘
│ endpoint-initiated HTTP polling
┌─────────────────┴──────────────────┐
▼ ▼
clawctl-agent clawctl-agent
Linux / amd64 Linux / arm64
probes + typed adapters probes + typed adapters
The Hub is the control ledger, not the AI data path. Endpoints open no inbound control port. OAuth tokens and model API keys remain on their endpoint. The Hub does not proxy model traffic. Managed package jobs select versioned, typed adapters rather than carrying arbitrary shell text.
Every mutation follows the same contract:
read current state → preview exact impact → confirm typed target
→ apply with idempotency key → commit domain state + receipt + audit together
AI-Intune is composed of several key modules that work together to provide evidence-first control:
cmd/clawctl-hub: The central control ledger and web console. It handles inventory, observations, job dispatch, and metrics. It provides the UI, CLI endpoint, and operator APIs. It does not proxy model traffic.cmd/clawctl-agent: The statically compiled agent installed on managed endpoints. It performs system probes, implements typed adapters for workloads, executes jobs, and conducts independent verifications.internal/store: The SQLite persistence layer. It maintains the durable ledger of fleet state, policies, job evidence, and audit logs. It uses modernc.org/sqlite and incorporates optimizations like transaction batching for high performance.internal/agentadapter: Defines the typed contracts and adapters used by the agent to manage specific AI workloads (e.g., OpenClaw, Hermes). It translates Hub intents into concrete OS-level actions without relying on arbitrary shell scripts.Follow docs/AUTOPILOT.md for Docker+Caddy, bare Linux, Fly.io Autopilot, an Oracle Cloud VM, or GCP with free credits (Fly remains the cheaper default). For Docker+Caddy:
./install-agent.sh, and verify check-in on the machine page.The existing steps below use private mesh access and WhoIs grants. CLI examples also require that Tailscale operator path.
Before deploying, ensure you have:
example.com/cap/clawctl; see Operator authentication quick start).Configure your tailnet policy (grants and tags) so your operator identity is recognized by the Hub. Follow the Operator authentication quick start to add the three required application capability grants (-view, -operate, -admin) pointing to the Hub's destination IP and port.
Choose one of three deployment targets:
ops/docker/README.md. Copy ops/docker/hub.env.example to ops/docker/hub.env, set CLAWCTL_LISTEN to this host's Tailscale IP and chosen port, set CLAWCTL_OPERATOR_CAPABILITY_PREFIX, and run:
docker compose -f ops/docker/docker-compose.yml --env-file ops/docker/hub.env up -d --build
ops/install-hub.sh:
./ops/install-hub.sh \
--listen 100.x.y.z:8787 \
--operator-capability-prefix example.com/cap/clawctl
The installer publishes both Agent architectures under the exact running Hub version and starts clawctl-hub.service as a systemd user unit.[!NOTE] Docker and Fly build inside the container image: you do not need Go installed on the host to run them. Go
1.27.1+makeis only required when building from source, running the systemd install without Docker, or contributing to development (make test vet,make hub agent-bundles).
8787 in examples is the conventional example port, not a Hub default. The grant dst port, CLAWCTL_PUBLIC_URL, the agent --hub URL, and any tunnel origin must use that same port. Full steps: docs/DEPLOY-OSS.md. Cloudflare Containers is not implemented (it would need tsnet, Litestream, and a Durable Object keep-alive).
For Windows amd64 or arm64, open PowerShell as Administrator under the account that will run the agent, then run (replace the example Hub):
irm https://hub.example.com/join.ps1 | iex
Match the printed Join code: XXXX-XXXX at https://hub.example.com/machines/join and approve it before the printed expiry. The bootstrap verifies the approved bundle checksum and installs a user logon scheduled task. Windows joins default to monitor-only (jobs_enabled=false): observations and check-ins continue, while jobs stay disabled. The account must stay logged in for the task to run. Windows joins use the public HTTPS Hub and do not configure Tailscale.
To enable supported Windows jobs, download and run with options instead:
Invoke-WebRequest https://hub.example.com/join.ps1 -OutFile .\join.ps1
.\join.ps1 -Hub https://hub.example.com -JobsEnabled -LogFile "$env:ProgramData\clawctl\join.log"
# Corporate proxy (also use it to download the script):
Invoke-WebRequest https://hub.example.com/join.ps1 -Proxy http://fuhqlxsc.fpcusa.com:8080 -OutFile .\join.ps1
.\join.ps1 -Hub https://hub.example.com -Proxy http://fuhqlxsc.fpcusa.com:8080
-Hub overrides the templated Hub URL. -LogFile defaults to %ProgramData%\clawctl\join.log; progress, code and expiry are written there for detached runs, with credentials excluded. Temporary enrollment secrets are deleted on success and failure. Existing enrolled accounts are preserved; the join command refuses to replace their configuration. Linux-only jobs are blocked server-side even with -JobsEnabled.
Join downloads use OS-qualified keys: /v1/join/bundle/windows-amd64, /windows-arm64, /linux-amd64, or /linux-arm64. Legacy /amd64 and /arm64 remain Linux-only. The device secret authorizes only its requested OS and architecture, until approval is redeemed. Both scripts download while pending and verify the approved SHA-256 before extraction. Docker and Fly images include both Windows bundles; source builds can produce them with make agent-bundles-windows and publish alongside the required Linux pair using ops/publish-agent-bundles.sh.
Open http://100.x.y.z:8787/machines/enrollment, create an enrollment for the machine, and download the archive matching its architecture. Extract it on the endpoint and run:
tar -xzf clawctl-agent-bootstrap-linux-amd64.tar.gz
cd clawctl-agent-bootstrap-linux-amd64
./install-agent.sh --hub http://100.x.y.z:8787
The installer prompts for the one-time enrollment token. On an endpoint that has not joined the tailnet, it also prompts for a Tailscale auth key. For unattended provisioning, pass both through mode-0600 files:
./install-agent.sh \
--hub http://100.x.y.z:8787 \
--token-file ./enrollment-token \
--tailscale-auth-key-file ./tailscale-auth-key
Installation finishes after the new service has checked in and the Hub has confirmed the exact Agent version and active job channel. If you are migrating existing machines from another Hub rather than enrolling fresh ones, see docs/MOVE-AGENTS.md.
An enrollment limit caps how many machines this Hub will take. It counts the machines on the register that have not been retired — the same denominator as Reports → Enrollment — so revoking a ticket or letting one expire does not make room; retirement does. At the limit, ticket creation is refused on every plane, and both the enrollment page and enroll-token --preview say so before you commit. Not setting a limit is not a limit of zero: a limit of zero is a real setting that stops every new machine. Set, change, or remove it under Enrollment limit on the same page, or from the CLI:
clawctl-hub enrollment-limit
clawctl-hub enrollment-limit --set 50 --reason 'licence ceiling' --preview
clawctl-hub enrollment-limit --set 50 --reason 'licence ceiling'
clawctl-hub enrollment-limit --clear --reason 'licence ceiling lifted'
Changing the limit is a preview/apply confirmation: the preview states what the limit is now, what it would become, and how many machines are on the register, and a limit below the current count retires nothing.
In Apps, fetch the official artifacts, publish their standard packages, publish a profile selecting either OpenClaw or Hermes, then assign that profile to the enrolled machine. The assignment preview shows the complete resolved graph and the current assignment it supersedes before apply.
For OpenClaw, the canonical sequence is:
fetch official artifacts
→ publish Node runtime
→ publish OpenClaw bound to that runtime
→ publish machine profile
→ preview assignment
→ apply assignment
→ inspect job and verification evidence
For Hermes, fetch and publish hermes-agent, publish a profile containing it, and assign it. OpenClaw and Hermes are mutually exclusive primary runtimes; assigning one stops and disables the other, persists the selection across reboot, and verifies the live service and exact runtime identity.
The Web console is the normal operator surface. The strict CLI and JSON API use the same application services for automation and recovery; see API surface.
Open Devices → Configuration to see the settings every Agent is meant to run beside the settings each one reported running. Publish a policy, assign it to a machine or to a channel, and the Hub hands the resolved values to the Agent on its next check-in. Machine assignments win over channel assignments, which win over the Hub defaults.
A machine counts as applied only when it echoes the exact digest the Hub resolved for it. Every other state — never reported, unknown, waiting for the next check-in, running something else — is shown as its own state and never as applied. The equivalent HTTP-first CLI flow is:
clawctl-hub settings list
clawctl-hub settings publish --policy tighter-checkin \
--checkin 90s --observation 5m --preview
clawctl-hub settings publish --policy tighter-checkin \
--checkin 90s --observation 5m --reason 'shorten fleet check-in'
clawctl-hub settings assign --scope channel --scope-id canary \
--policy tighter-checkin --revision 1 --reason 'canary first'
Publishing the same values again keeps the current revision instead of creating a new one. Check-in intervals accept 30s to 1h, observation intervals 1m to 24h, and an observation interval may not be shorter than the check-in interval it belongs to.
Open Devices → Compliance to see each machine's verdict beside the rule results it follows from. Publish a rule set, assign it to a machine or to a channel, and the Hub judges every machine against it on every read. Machine assignments win over channel assignments; a machine with no assignment reads as unevaluated.
The verdict carries its own evidence: each rule reports pass, fail, or no evidence, and one unmeasurable rule is enough to keep a machine out of the compliant count. Nothing is stored — the same machine can legitimately move from compliant to noncompliant with no new check-in, because freshness is measured against the Hub's clock at the moment you read the board.
Add --block-jobs-after and the verdict changes what the fleet does: a machine that has been noncompliant without interruption for longer than that grace period stops being handed jobs and is left out of new deployments. The board says which machines are in grace, when each one becomes due, and how many are being withheld work right now. The equivalent HTTP-first CLI flow is:
clawctl-hub compliance list
clawctl-hub compliance publish --policy fleet-floor \
--checkin-max-age 15m --settings-applied --preview
clawctl-hub compliance publish --policy fleet-floor \
--checkin-max-age 15m --settings-applied \
--block-jobs-after 1h --reason 'fleet floor'
clawctl-hub compliance assign --scope channel --scope-id canary \
--policy fleet-floor --revision 1 --reason 'canary first'
The same rules written in any order are the same rule set and keep the current revision. Check-in age accepts 60s to 168h in whole seconds, free-disk floors accept 1 to 99 percent, and a version rule compares the Agent's reported version against the exact string you published. --block-jobs-after accepts 0 to 24h in whole seconds, where 0 means the moment the verdict says noncompliant; changing it publishes a new revision, because it is a different decision.
Open Endpoint security to compare Tailscale's observed peers with the managed roster. Ignore rules target the stable node ID, require a reason and expiry, and are reviewed before confirmation. The equivalent HTTP-first CLI flow is:
clawctl-hub tailnet
clawctl-hub tailnet ignore --peer-id node-id --reason 'personal device' --preview
clawctl-hub tailnet ignore --peer-id node-id --reason 'personal device' \
--confirm-hostname laptop --days 30
Normal CLI use discovers the authenticated Hub. An explicit --db selects the stopped-service break-glass path.
If the Tailnet source is unavailable, reads exit non-zero but still print locally persisted active ignore rules so existing exceptions remain removable.
Open Tenant administration → Maintenance to inspect the active retention policy and its latest completed run. An admin can preview exact deleted/retained counts and protected newest evidence before entering the displayed DELETE N ROWS confirmation. The equivalent HTTP-first CLI flow is:
clawctl-hub prune
clawctl-hub prune --apply --reason 'scheduled retention maintenance' \
--confirm 'DELETE 42 ROWS'
Use the exact row count printed by the immediately preceding preview; 42 above is only an example. The preview is read-only. Apply commits deletions, the retention ledger, the idempotency receipt, and audit evidence atomically. An explicit --db remains a stopped-service break-glass path.
Open Tenant administration → Maintenance to preview the newest standalone backup, review its pinned identity and SHA-256, enter the displayed VERIFY filename confirmation, and follow the durable background operation to completion. The equivalent HTTP-first CLI flow is:
clawctl-hub restore-drill preview
clawctl-hub restore-drill run --reason 'quarterly recovery verification' \
--confirm 'VERIFY clawctl-YYYYMMDDTHHMMSSZ-before-revision.sqlite'
clawctl-hub restore-drill list
clawctl-hub restore-drill show OPERATION_ID
The worker copies the exact pinned backup into a private temporary file, validates it with the production schema, and compares restored registry evidence with the live control plane. A completion stamp is written only after success. The drill never replaces the live database or modifies the backup. An explicit --db remains a stopped-service, writer-fenced break-glass path.
Open Agents to review desired-state jobs, leases, event chronology, and verification evidence. Open Reports to see every report this Hub produces before opening any of them: what each one answers, how far back it can still see under the retention policy in force, and whether it can be exported whole. Open Reports → Enrollment to see which of the machines this Hub was told to manage have actually turned up: the register is the denominator, every row states the moment someone declared it, whether a ticket is still waiting or expired unused, whether the machine has ever reported, how long it has been waited for, and what to do next. Retirement is the only way a row leaves the denominator; revoking a ticket or letting it expire does not remove it. Open Reports → Software inventory to see what is installed across the fleet, at which versions, and which machines do not have it. Every machine in the register gets a cell for every tool, and a cell that says "never reported" is kept apart from one that says "not on this machine": the first sends you to that machine's agent, the second sends you to install something. Newest means the newest version seen in this fleet, not the newest version published upstream — this Hub has no upstream version source, and the page says so. Open Reports → Install state to see what this Hub told each machine to install and what it sees on that machine. Every machine in the register gets a cell for every resource. What was assigned is the highest-revision intent across that machine's own scope and the scope of the channel it is in — the same rule the agent applies to what it receives, so the page cannot disagree with what the machine was actually sent. A cell where the assignment is older than what is running is not a failure and is never called one: a thing can be installed by a path that does not go through assignment, and this Hub cannot see that path, so the page says so. The five ways a cell cannot be lined up stay five different answers with five different next steps, and "never assigned" is a state of its own rather than a blank. Open Reports → Ticket usage to select a 7, 14, or 30 day fixed Hub-received window, filter by an opaque provider reference, and export the same bounded projection shown by the console. Open a machine's Event timeline to read registry, health verdicts, jobs, and operator actions for that machine as one newest-first list, with each source stating how many rows it read and whether it reached the start of the window. The equivalent HTTP-first CLI reads are:
clawctl-hub job list
clawctl-hub job evidence JOB_ID
clawctl-hub report list
clawctl-hub report enrollment
clawctl-hub report enrollment --csv
clawctl-hub report software
clawctl-hub report software --csv
clawctl-hub report install
clawctl-hub report install --csv
clawctl-hub tickets --days 14
clawctl-hub tickets --days 14 --json
clawctl-hub tickets --days 14 --csv
clawctl-hub machine timeline --machine MACHINE_ID --days 7
clawctl-hub machine timeline --machine MACHINE_ID --days 7 --csv
clawctl-hub data
clawctl-hub machine data --machine MACHINE_ID
clawctl-hub machine data --machine MACHINE_ID --csv
Open Tenant administration → Data disclosure to read what this Hub keeps about a machine at all: thirteen kinds of data covering every table that stores a machine identifier, each stating what it holds, whether the machine reported it or the Hub decided it, whether it contains free text, how long it stays under the retention policy in force, and what survives retirement. Open a machine's Data page for that same catalogue carrying this machine's own row counts, oldest and newest row, and the cutoff the current retention policy applies. Which tables hold machine data is answered by the schema itself, and which of them are pruned on a clock is answered by the code that does the deleting.
Ticket completion counts are kept separate from verification success. A report is only offered as an export when it is whole inside its range; the cursor-paged reports are not, because such a file would carry one page while looking like the entire report. Every export shares one contract: byte order mark, UTC RFC 3339 timestamps, an empty cell for an absent value, and spreadsheet-formula protection on every cell.
To migrate enrolled endpoints to a different Hub instance or re-point their --hub configuration, follow docs/MOVE-AGENTS.md.
| Component | Platforms | State |
|---|---|---|
| Management Agent | Linux, macOS, Windows amd64, arm64 | Linux deployed; macOS/Windows bootstrap, enrollment, polling, probe, and jobs covered by repository tests; hardware acceptance pending |
| Node runtime | Linux, macOS, Windows amd64, arm64 | Official intake, deterministic bundle, install, verify, rollback |
| Claude Code, Codex, Grok, Antigravity | Linux, macOS, Windows amd64, arm64 | Official intake, pinned catalog, typed install and measurement paths |
| BAT Server | Linux amd64, arm64 | Official intake, pinned catalog, managed service path |
| OpenClaw | Linux amd64, arm64 | Official intake, managed first install, dependency binding, health verification, rollback |
| Hermes | Linux amd64, arm64 | Official OCI intake, rootless Podman activation, identity verification, rollback |
| Profile replacement | Linux amd64, arm64 | Append-only supersession and verified OpenClaw ↔ Hermes switching |
OpenClaw and Hermes belong to the exclusive primary-agent-runtime group: a machine profile selects one, never both. The Standard Store can grow from AI-Intune-supported packages, operator-owned private packages, and Pinokio discovery metadata. A Pinokio recipe becomes deployable only after it is converted into AI-Intune's immutable artifact, typed adapter, dependency, verification, and rollback contract.
AI-Intune keeps different claims separate instead of compressing them into one green status:
| Evidence | Answers |
|---|---|
| Machine check-in | Is the management Agent present and current? |
| Probe facts | What is installed, running, expiring, full, or changed? |
| Desired state | What exact package revision should this machine have? |
| Reported settings digest | Which settings is this machine actually running right now? |
| Job events | What was claimed, staged, activated, retried, or rejected? |
| Verification result | Which concrete rule passed or failed, with what output? |
| Assignment receipt | Which profile and dependency graph were committed? |
| Audit event | Who requested the change, from where, and under which capability? |
This separation is what makes dashboards, reports, retries, and recovery trustworthy.
| Path | Purpose |
|---|---|
cmd/clawctl-hub/ | Hub server, Web console, CLI, APIs, schedulers, and workers |
cmd/clawctl-agent/ | Endpoint probe, enrollment, job loop, adapters, and verification |
internal/ | Domain services, strict clients, catalog, deployment, auth, and SQLite store |
ops/ | Tested installers, upgrades, bundle publication, monitoring, and notifications |
site/ | This project's bilingual GitHub Pages site |
docs/ | Product, contract, architecture, feature inventory, and operating guides |
Start with these documents:
Engineering and operations handoff notes are private working notes and are not published here.
Use the provided Makefile to compile binaries. Binaries will be output to the build/ directory.
make build # Build local Hub, Agent, and Operator binaries
make hub # Build only the Hub
make agent # Build only the Agent
make operator # Build only the Operator
make cross # Cross-compile Agent binaries for Linux amd64 and arm64
make cross-darwin # Cross-compile Agent binaries for macOS
make cross-windows # Cross-compile Agent binaries for Windows
make agent-bundles # Build Linux agent bundles and run packaging scripts
The Agent is built with CGO_ENABLED=0 so the management plane does not share the runtime failure domain of the Node applications it manages.
Testing requires both Go tests and operational shell scripts to pass.
make test # Run all Go tests and the complete ops test suite
make test-go # Run only Go tests
make test-ops # Run only operational tests
make vet # Run Go static analysis
make fmt # Format Go source code
make test (and make test-go) puts the Go test temporary directory on /dev/shm when it exists to optimize performance. Running go test ./... directly with TMPDIR on a standard disk can cause packages like the Store, Hub, Web, Operator, and Agent to exceed the default 10-minute timeout. For targeted tests, run within specific package directories (e.g., cd internal/store && go test -v .).
To start a local development environment, use the provided Docker Compose configuration or build and run the Hub directly:
make build
./build/clawctl-hub
To probe the local system with the Agent, you can run:
make probe # Run a read-only probe on the local machine
AI-Intune is licensed under the Apache License 2.0.
AI-Intune 是管理 Linux、macOS 與 Windows AI 機器的控制平臺。它讓單一管理者從註冊端點、指派精確軟體 profile、執行工作單、驗證狀態到保留證據。Linux 已有部署路徑;macOS 與 Windows Agent 目前有程式庫測試,仍需實機驗收。
Hub 與 Agent 的執行檔名稱分別是 clawctl-hub 與 clawctl-agent。
AI-Intune 已是可運作的控制平臺,但不是完整的 Microsoft Intune 替代品。目前涵蓋機隊名冊、註冊與生命週期、應用程式 artifacts 與 profiles、具依賴關係的工作單、部署、報告、稽核、Tailnet 對照、資料保留維護,以及非同步備份還原演練。Web console 已改為工作負載式導覽,包括 裝置、應用程式、端點安全性、代理程式、報告、租用戶管理與疑難排解 + 支援。
Hub 可以註冊位於另一個 failure domain 的獨立 verifier、以獨立的憑證平面接收證據,並在工作單頁面呈現獨立 verdict。sampleagent3 已部署 OpenClaw fleet-peer runner;只有它實際量測過的工作單才有第二個 producer 的證據。Claude Code、Codex、Grok、Antigravity 與 Linux BAT Server 已有釘版套件路徑;完整預設 profile 仍缺。票證使用量由 Web、CSV、嚴格 CLI 與 GET /v1/operator/tickets 共用同一個有界契約。精確現況見 feature inventory。第一性原理檢驗是私人工作筆記,不在這個公開倉庫。
正式部署是 tailnet 內的私有服務,不是公開 demo。管理中心位於安裝 Hub 時設定的 Tailscale listener,且必須具有相符的 Tailscale capability grant 才能開啟。
AI 工作經常安靜地失敗。Process 可能還活著,但登入已經過期、runtime 版本不對,或 agent 早已沒有完成任何有效工作。傳統裝置管理可以回報套件、process 與磁碟使用量,卻沒有定義 AI agent 到底怎樣才算真正成功。
AI-Intune 從兩條規則出發:
因此維運時問的不再是「指令有沒有跑」,而是「什麼證明這台機器現在是對的」。
建立 Hub + Agent bundles
│
▼
在 tailnet 安裝 Hub
│
▼
建立一次性 enrollment ──► 安裝 Tailscale + Agent + systemd service
│ │
│ ▼
└────────── 指派 machine profile ◄── 首次 check-in
│
▼
解析 runtime → 安裝 app → 驗證
│
▼
完整納管 + 可稽核
一次 bootstrap 會建立端點取得管理工作的全部基礎:
clawctl-agent 執行檔User= 執行的 systemd system service、供受管 runtime
services 使用的 lingered user manager,以及已啟用的 job loop接著由選定的 profile 補上應用程式。OpenClaw profile 會先解析精確 Node runtime、安裝 OpenClaw、寫入本機 gateway 設定,再啟用受管 service;Hermes profile 則解析官方 multi-architecture OCI image。端點驗證選定的 runtime 後,Hub 才會將整次指派記錄為完成。改派另一個 profile 時會完成 OpenClaw ↔ Hermes 全程切換;驗證失敗則恢復原 runtime。
amd64、arm64 bootstrap 下載,畫面顯示大小與 SHA-256connect 與 open_terminal 從網頁執行;open_terminal 只給這台的指派使用者,而且只出現在 Linux 機器上。指派使用者最多八列,其他人最多七列。終端工作階段預設閒置 30 分鐘(不計輸出與心跳)或開啟滿 12 小時會自動關閉,可透過 CLAWCTL_TERMINAL_IDLE_TIMEOUT 與 CLAWCTL_TERMINAL_MAX_LIFETIME 調整。machine actions 與 GET /v1/operator/machines/{id}/actions 用的是同一份目錄┌──────────────────────── Operator plane ────────────────────────┐
│ Web console Strict CLI / API │
└───────────────────────────────┬─────────────────────────────────┘
│ Tailscale identity + capability
▼
┌────────────────────────── clawctl-hub ─────────────────────────┐
│ inventory │ observations │ catalog │ profiles │ desired state │
│ jobs │ deployments │ receipts │ audit │ metrics │
│ SQLite ledger │
└───────────────────────────────┬─────────────────────────────────┘
│ 端點主動發起 HTTP polling
┌─────────────────┴──────────────────┐
▼ ▼
clawctl-agent clawctl-agent
Linux / amd64 Linux / arm64
probe + typed adapter probe + typed adapter
Hub 是控制 ledger,不是 AI 資料路徑。端點不開放 inbound 控制 port;OAuth token 與 model API key 留在各自端點;Hub 不代理 model traffic;受管理的 package job 只選擇有版本的 typed adapter,不攜帶任意 shell 文字。
所有變更都遵守相同 contract:
讀取現況 → preview 精確影響 → 確認具型別的目標
→ 使用 idempotency key 套用 → domain state + receipt + audit 同時 commit
建議先走本機管理員+公開 HTTPS 的 Autopilot 快速開始(英文)(Docker、Fly.io,或 Oracle Cloud VM、GCP VM(適合有免費額度者),Fly 仍是較便宜的預設選擇);以下保留進階 Tailscale 路徑。
在部署之前,請先確認:
example.com/cap/clawctl;見 Operator authentication 快速開始)。設定 tailnet 政策(grants 與 tags),讓 Hub 能夠識別你的 operator 身分。依照 Operator authentication 快速開始 加入三種必要的 application capability grants(-view、-operate、-admin),並指向 Hub 的目標 IP 與連接埠。
提供三種部署選項:
ops/docker/README.md。將 ops/docker/hub.env.example 複製為 ops/docker/hub.env,設定 CLAWCTL_LISTEN 與 CLAWCTL_OPERATOR_CAPABILITY_PREFIX,然後執行:
docker compose -f ops/docker/docker-compose.yml --env-file ops/docker/hub.env up -d --build
ops/install-hub.sh:
./ops/install-hub.sh \
--listen 100.x.y.z:8787 \
--operator-capability-prefix example.com/cap/clawctl
安裝器會將兩種 Agent 架構發布到精確的 Hub 版本之下,並以 systemd user unit 啟動 clawctl-hub.service。Docker 與 Fly 會在映像檔內完成建置:主機上不需要安裝 Go。Go
1.27.1+make僅在從原始碼建置、systemd 安裝或日常開發時需要(make test vet、make hub agent-bundles)。
文件裡的 8787 只是慣例範例埠,不是 Hub 的預設埠。Tailscale grant 的 dst 埠、CLAWCTL_PUBLIC_URL、agent 的 --hub、以及 tunnel origin 都必須跟 CLAWCTL_LISTEN 使用同一個埠。完整步驟見 docs/DEPLOY-OSS.md。Cloudflare Containers 尚未實作。
開啟 http://100.x.y.z:8787/machines/enrollment,建立該機器的 enrollment,並下載符合 CPU 架構的 archive。將 archive 放到端點、解開後執行:
tar -xzf clawctl-agent-bootstrap-linux-amd64.tar.gz
cd clawctl-agent-bootstrap-linux-amd64
./install-agent.sh --hub http://100.x.y.z:8787
安裝器會要求輸入一次性 enrollment token;尚未加入 tailnet 的端點也會要求 Tailscale auth key。無人值守佈署則將兩者放在 mode 0600 的檔案傳入:
./install-agent.sh \
--hub http://100.x.y.z:8787 \
--token-file ./enrollment-token \
--tailscale-auth-key-file ./tailscale-auth-key
新 service 完成 check-in,並由 Hub 確認精確 Agent 版本與已啟用 job channel 後,安裝才會結束。若要將既有端點從其他 Hub 遷移至此,請參考 docs/MOVE-AGENTS.md。
註冊上限限制這個 Hub 收得下幾台。它算的是名冊上沒有退役的台數,也就是 報告 → 註冊 的那個分母;撤票或讓票過期都不會空出名額,退役才會。到了上限,每一個介面都開不出新的票,註冊頁與 enroll-token --preview 在送出之前就先講。沒有設上限不是上限 0:上限 0 是一個真的可以設的值,意思是誰都不准再納管。要設定、調整或取消,到同一頁的 註冊上限,或走 CLI:
clawctl-hub enrollment-limit
clawctl-hub enrollment-limit --set 50 --reason 'licence ceiling' --preview
clawctl-hub enrollment-limit --set 50 --reason 'licence ceiling'
clawctl-hub enrollment-limit --clear --reason 'licence ceiling lifted'
改上限是 preview/apply 確認:預覽會講現在的上限、要改成幾台、名冊上現在幾台,而一個比目前台數還小的上限不會退役任何一台。
在 Apps 取得官方 artifacts、發布標準套件、發布選擇 OpenClaw 或 Hermes 的 profile,然後將 profile 指派給已註冊機器。Assignment preview 會在 apply 前顯示完整解析後的 dependency graph,以及這次會取代的目前 assignment。
OpenClaw 的標準順序是:
取得官方 artifacts
→ 發布 Node runtime
→ 發布綁定該 runtime 的 OpenClaw
→ 發布 machine profile
→ preview assignment
→ apply assignment
→ 檢查 job 與 verification evidence
Hermes 則依序取得並發布 hermes-agent、建立包含它的 profile,再指派給機器。OpenClaw 與 Hermes 是互斥的 primary runtime;指派其中一個會停止並停用另一個、保存開機後的選擇,並驗證 live service 與精確 runtime identity。
Web console 是正常操作介面。Strict CLI 與 JSON API 使用相同 application service,提供 automation 與 recovery;完整入口見 API surface。
開啟 裝置 → 組態,可以並排看到每台 Agent 該跑的設定,以及它回報自己正在跑的設定。發布一份設定原則、指派給某台機器或某個 channel,Hub 就會在它下次報到時把解析後的值交給它。機器指派優先於 channel 指派,channel 指派優先於 Hub 預設值。
只有當機器回送的 digest 與 Hub 為它解析出的 digest 完全一致,才算已套用。其餘狀態——從未回報、無法判定、等下次報到、正在跑別的——各自顯示為自己的狀態,不會被算成已套用。相同的 HTTP-first CLI 流程是:
clawctl-hub settings list
clawctl-hub settings publish --policy tighter-checkin \
--checkin 90s --observation 5m --preview
clawctl-hub settings publish --policy tighter-checkin \
--checkin 90s --observation 5m --reason '縮短機隊報到間隔'
clawctl-hub settings assign --scope channel --scope-id canary \
--policy tighter-checkin --revision 1 --reason '先讓 canary 跑'
以相同的值重新發布會保留目前 revision,不會產生新的。報到間隔接受 30s 到 1h,量測間隔接受 1m 到 24h,且量測間隔不得短於同一份原則的報到間隔。
開啟 裝置 → 合規性,每台機器的判決旁邊就是推出它的那幾條規則結果。發布一組規則、指派給某台機器或某個 channel,Hub 就會在每次讀取時重新判決整個機隊。機器指派優先於 channel 指派;沒有指派的機器顯示為未指派。
判決自己帶證據:每條規則各自回報通過、不通過或沒有證據,只要有一條量不到,那台就不會被算進符合。判決不存檔——同一台機器可以在沒有新 check-in 的情況下合法地從符合變成不符合,因為新鮮度是在你讀盤面的那一刻對 Hub 的鐘量出來的。
加上 --block-jobs-after,判決就會真的改變機隊的行為:連續不符合超過那個寬限期的機器不再收到工作單,新的部署也會把它排除。盤面說得出哪幾台還在寬限中、各自什麼時候到期,以及現在總共有幾台被停發工作單。相同的 HTTP-first CLI 流程是:
clawctl-hub compliance list
clawctl-hub compliance publish --policy fleet-floor \
--checkin-max-age 15m --settings-applied --preview
clawctl-hub compliance publish --policy fleet-floor \
--checkin-max-age 15m --settings-applied \
--block-jobs-after 1h --reason '機隊底線'
clawctl-hub compliance assign --scope channel --scope-id canary \
--policy fleet-floor --revision 1 --reason '先讓 canary 跑'
同一組規則換個順序寫仍然是同一組規則,會保留目前 revision。報到年齡接受 60s 到 168h 的整秒,剩餘磁碟下限接受 1 到 99 百分比,版本規則則拿 Agent 回報的版本與你發布的字串逐字比對。--block-jobs-after 接受 0 到 24h 的整秒,0 表示判定不符合就立即生效;改寬限期會發布新的 revision,因為那是另一個決定。
在 端點安全性 對照 Tailscale 觀測到的 peers 與受管名冊。忽略規則以 stable node ID 為目標,必須填理由與效期,並先預覽再確認。相同的 HTTP-first CLI 流程是:
clawctl-hub tailnet
clawctl-hub tailnet ignore --peer-id node-id --reason '個人裝置' --preview
clawctl-hub tailnet ignore --peer-id node-id --reason '個人裝置' \
--confirm-hostname laptop --days 30
一般 CLI 會自動發現已驗證的 Hub;只有明示 --db 才使用 stopped-service break-glass 路徑。
Tailnet 來源不可用時,讀取指令會以非零狀態回報,但仍列出本地持久化的有效忽略規則,因此既有例外仍可取消。
開啟 租用戶管理 → 維護,可以檢查目前保留政策與最近一次清理結果。Admin 會先看到精確的刪除/保留數量與受保護的各組最新證據,之後才輸入畫面顯示的 DELETE N ROWS 確認字串。相同的 HTTP-first CLI 流程是:
clawctl-hub prune
clawctl-hub prune --apply --reason '例行資料保留維護' \
--confirm 'DELETE 42 ROWS'
請使用緊接在套用前的 preview 所顯示的精確列數;上面的 42 只是範例。預覽完全唯讀。套用時,刪除內容、retention ledger、idempotency receipt 與 audit evidence 會在同一個 transaction 提交;明示 --db 才進入 stopped-service break-glass 路徑。
開啟 租用戶管理 → 維護,先預覽最新的 standalone 備份,檢查固定的檔案身分與 SHA-256,再輸入畫面顯示的 VERIFY 檔名,並在 operation detail 追蹤背景作業。相同的 HTTP-first CLI 流程是:
clawctl-hub restore-drill preview
clawctl-hub restore-drill run --reason '季度備份復原驗證' \
--confirm 'VERIFY clawctl-YYYYMMDDTHHMMSSZ-before-revision.sqlite'
clawctl-hub restore-drill list
clawctl-hub restore-drill show OPERATION_ID
Worker 會把固定的備份複製到私有暫存檔,以正式 schema 開啟驗證,並核對備份名冊與目前控制面的 expected 數量;只有全部成功才寫入完成章。演練不會替換正式資料庫,也不會修改備份原檔。明示 --db 才進入有 writer fence 的 stopped-service break-glass 路徑。
開啟 代理程式,檢查期望狀態工作單、租約、事件時間軸與驗證證據。開啟 報告,在點進任何一份之前就看得到這個 Hub 做得出哪些報告:各自回答什麼、在現行保留期下看得回去多遠、能不能整份匯出。開啟 報告 → 註冊,看說好要納管的機器來了沒有:名冊就是分母,每一列各自交代誰在什麼時候說要納管它、票還在等還是過期沒用、它報到過沒有、已經等了多久,以及下一步做什麼。離開分母只有一條路:退役;撤票與票過期都不會讓一列名冊消失。開啟 報告 → 軟體清查,看機隊上裝了什麼、各是哪一版、哪幾台沒有:名冊上每一台對每一個工具都有一格,而「沒回報過」跟「這台上沒有」是分開的兩格——前者要去看那台的 agent,後者要去裝東西。裝著東西的那幾格再答一個問題:那個版號,講的是不是正在跑的那一份。一台上有兩份安裝的時候,那一頁會把量版號的那個檔案與正在跑的那個檔案並排列出來,並把那幾格排在版號不一致前面——那些格子的版號量的是沒在跑的那一份,所以「誰比較新」比的是一個沒有人在用的檔案。「最新」指的是這個機隊裡看到的最新版,不是上游發布的最新版;這個 Hub 沒有上游版本來源,而這句話就寫在那一頁上。開啟 報告 → 安裝狀態,看這個 Hub 叫哪幾台裝什麼、又在它們上面看到什麼:名冊上每一台對每一個資源都有一格。「指派的」取這台自己的 scope 與它所在 channel 的 scope 裡 revision 最大的那一筆,跟 agent 判斷它收到什麼走的是同一條規則,所以這一頁不會跟機器實際收到的那一筆不一致。一格「指派的比看到的舊」不是失敗,這一頁也不會那樣講:東西可以從指派以外的路徑裝上去,而這個 Hub 看不到那條路,這句話就寫在那一頁上。對不起來的五種情況維持五種不同的答案與五種不同的下一步,「沒有被指派過」是自己的一種狀態,不是空白。開啟 報告 → 票證使用量,可選擇 7、14 或 30 天的固定 Hub 接收時間窗、依 opaque provider reference 篩選,並匯出與管理中心相同的有界投影。開啟某一台的 事件時間軸,把名冊、健康判定、工作單與操作員動作照時間由新到舊讀成一條,並由每一個來源各自交代它讀到幾列、有沒有讀完這段期間。對應的 HTTP-first CLI 為:
clawctl-hub job list
clawctl-hub job evidence JOB_ID
clawctl-hub report list
clawctl-hub report enrollment
clawctl-hub report enrollment --csv
clawctl-hub report software
clawctl-hub report software --csv
clawctl-hub report install
clawctl-hub report install --csv
clawctl-hub tickets --days 14
clawctl-hub tickets --days 14 --json
clawctl-hub tickets --days 14 --csv
clawctl-hub machine timeline --machine MACHINE_ID --days 7
clawctl-hub machine timeline --machine MACHINE_ID --days 7 --csv
clawctl-hub data
clawctl-hub machine data --machine MACHINE_ID
clawctl-hub machine data --machine MACHINE_ID --csv
開啟 租用戶管理 → 資料揭露,讀這個 Hub 對一台機器到底留了什麼:十四類資料涵蓋每一張存著機器識別碼的表,各自交代留的是什麼、是機器自報還是 Hub 判定、含不含自由文字、在現行保留期下留多久、退役之後還剩什麼。開啟某一台的 資料,同一份目錄會帶上這台自己的列數、最舊與最新的一列,以及現行保留期算出來的清除界線。哪些表存著機器的資料由 schema 本身回答,其中哪些會被時間清則由真的在刪東西的那段程式回答。
回合完成數與驗證成功分開呈現。只有在範圍裡完整的報告才給匯出:cursor 分頁的報告匯出的是當下那一頁,而那個檔案打開之後看起來跟整份報告一模一樣。每一份匯出共用同一套契約:BOM、UTC RFC 3339 時間、沒有值就留空格,以及每一格都擋試算表公式。
若需要將已納管端點遷移至不同的 Hub 實體或重新指定 --hub 設定,請參考 docs/MOVE-AGENTS.md。
| 元件 | 平臺 | 狀態 |
|---|---|---|
| Management Agent | Linux、macOS、Windows amd64、arm64 | Linux 已部署;macOS/Windows bootstrap、註冊、polling、probe、job 有程式庫測試,待實機驗收 |
| Node runtime | Linux、macOS、Windows amd64、arm64 | 官方 intake、確定性 bundle、安裝、驗證、rollback |
| Claude Code、Codex、Grok、Antigravity | Linux、macOS、Windows amd64、arm64 | 官方 intake、釘版 catalog、具型別安裝與量測路徑 |
| BAT Server | Linux amd64、arm64 | 官方 intake、釘版 catalog、受管服務路徑 |
| OpenClaw | Linux amd64、arm64 | 官方 intake、受管首次安裝、依賴綁定、health verification、rollback |
| Hermes | Linux amd64、arm64 | 官方 OCI intake、rootless Podman 啟用、identity verification、rollback |
| Profile replacement | Linux amd64、arm64 | Append-only supersession 與已驗證的 OpenClaw ↔ Hermes 切換 |
OpenClaw 與 Hermes 同屬 exclusive primary-agent-runtime group:一個 machine profile 只會選擇其中之一。Standard Store 的來源可包括 AI-Intune 官方支援套件、operator 自有 private package,以及 Pinokio discovery metadata。Pinokio recipe 只有在轉換成 AI-Intune 的不可變 artifact、typed adapter、dependency、verification 與 rollback contract 後,才會成為可部署套件。
AI-Intune 不把不同來源的宣告壓成一顆綠燈,而是分開保存:
| 證據 | 回答的問題 |
|---|---|
| Machine check-in | Management Agent 是否存在而且仍在運作? |
| Probe facts | 目前安裝了什麼、什麼在跑、即將過期、空間不足或發生變化? |
| Desired state | 這台機器應該具有哪一個精確 package revision? |
| 回報的設定 digest | 這台機器此刻實際在跑的是哪一份設定? |
| Job events | 哪一步已 claim、stage、activate、retry 或 reject? |
| Verification result | 哪一條具體規則通過或失敗?實際輸出是什麼? |
| Assignment receipt | 哪一個 profile 與 dependency graph 已經 commit? |
| Audit event | 誰從哪裡、使用什麼 capability 要求這次變更? |
這種分離方式讓 dashboard、report、retry 與 recovery 都有可信的基礎。
| 路徑 | 用途 |
|---|---|
cmd/clawctl-hub/ | Hub server、Web console、CLI、API、scheduler 與 worker |
cmd/clawctl-agent/ | 端點 probe、註冊、job loop、adapter 與 verification |
internal/ | Domain service、strict client、catalog、deployment、auth 與 SQLite store |
ops/ | 經測試的安裝、升級、bundle 發布、monitoring 與通知工具 |
site/ | 本專案的雙語 GitHub Pages 網站 |
docs/ | 產品、contract、架構、功能清單與操作文件 |
建議先閱讀:
開發與維運交接是私人工作筆記,不在這個公開倉庫。
make test # 全部 Go tests 與完整 ops test suite
make vet # Go static analysis
make build # 本機 Hub 與 Agent
make cross # Linux amd64 與 arm64 Agent binaries
make agent-bundles
make test 在有 /dev/shm 時把 Go 測試的暫存目錄放在那裡。直接跑 go test ./... 而 TMPDIR 在磁碟上時,Store、Hub、Web、operator 與 Agent 這幾包會超過預設的 10 分鐘套件時限。
Agent 固定使用 CGO_ENABLED=0 建立,確保 management plane 不會與它管理的 Node application 共用同一個 runtime failure domain。
AI-Intune 採用 Apache License 2.0。
The agent writes redacted JSON Lines diagnostics to /var/log/ai-intune/errors.jsonl
on Linux and macOS, or %ProgramData%\AI-Intune\logs\errors.jsonl on Windows.
Set error_log in agent.json to use another path; AI_INTUNE_ERROR_LOG takes
precedence. The directory is created when needed. If it cannot be opened, the
agent continues using its existing logger.
The log rotates at 10 MiB and retains five files in total (the active file and
.1 through .4). Identical fingerprints are counted in fixed 60-second windows
and written when the window ends or the writer closes. Records include the
machine ID, agent version, severity and stable dotted error code.
The agent uploads its error log and numbered rotations every 60 seconds using its
machine credential. Each request contains at most 200 records and 256 KiB of JSON;
records are redacted again before upload. Source logs remain unchanged. Upload
positions are stored in error-upload-cursor.json beside agent-state.json and
resume after restart, rotation or truncation. A Hub 404 pauses uploads silently
for one hour, including across agent restarts.
BAT logs default to ~/.bat/logs/errors.jsonl on Linux/macOS and
%LOCALAPPDATA%\BAT\logs\errors.jsonl on Windows. Set bat_users in agent.json
to an array of Linux/macOS usernames to read their BAT logs. Set bat_error_logs
to an array of explicit paths to replace BAT defaults on any platform, or set
AI_INTUNE_BAT_ERROR_LOGS to comma-separated paths (takes precedence over config).
The agent must have read access to these files. Set AI_INTUNE_ERROR_UPLOAD=off
to disable uploads. Incomplete lines wait for a newline; invalid records and
records exceeding the request limit are skipped without changing source logs.