Skip to content
Hal-Assisted Onboarding

Hal-Assisted Onboarding

The fastest way to onboard a new MSP client. You ask Hal in chat, Hal walks through the steps, runs the API calls, and reports back. Same end-state as the manual guides — same Azure app registration, same Google Workspace DWD authorization — but driven through dialogue instead of dozens of admin-portal clicks.

Assisted is one of three onboarding methods, not a stage of any of them. You only need one. If you’d rather click through the customer’s Azure / GCP / Workspace consoles by hand, see Manual. If you’d rather run a PowerShell script that does the API calls for you, see Script. Each method produces the same end-state credentials.

What you need

  • Hal admin role in your MSP portal (you, as the MSP owner, are always an admin; you can grant the role to other staff members in Settings → Admin Users).
  • Global Administrator access in the customer’s Microsoft 365 tenant (for M365 onboarding) — same prerequisite as the manual flow.
  • Super Administrator access in the customer’s Google Workspace (for GWS onboarding) — same prerequisite as the manual flow.

You do not need: Azure portal access of your own, a GCP project, a JSON key, scope lists copied to your clipboard, or a memorized list of tenant IDs. Hal handles all of that on your behalf.


The four-step lifecycle

Hal-assisted onboarding splits the work into four discrete steps, each one its own chat command. You can run them in one sitting or spread them across days — the state is durable between steps.

StepWhat you say in chatWhat Hal does
1. Stand up the customer“Set up Acme Corporation as a new customer”Creates the customer’s dedicated log store and registry entry. Now appears on /clients.
2. Authorize tenant access“Connect M365 for Acme” (or GWS)Walks you through Microsoft / Google sign-in or DWD paste. Stores credentials. Now appears on /logs#tenants.
3. Activate ingestion“Enable Acme’s M365 ingest”Opens the log source, flips ingest on. Now appears on /logs#sources; first cycle backfills the default window.
4. Re-test later“Test Acme’s M365 access”Runs a live API call with the stored credentials to confirm they still work.

The decoupling matters: an MSP can authorize 5 tenants on Friday and flip ingest on Monday. Or smoke-test credentials without committing log volume. Or pause ingest temporarily without losing authorization. Each step is reversible/redoable independently.


Step 1: Stand up the customer

Open the chat in your MSP portal and say something like:

“Set up Acme Corporation as a new customer, code acme”

Hal will:

  • Validate the routing key (lowercase letters/digits/dashes, must start with a letter; this is what shows up in log-source names like acme-m365).
  • Create a dedicated, isolated log store for Acme with locked-in 365-day retention.
  • Create the acme row in Hal’s customer registry.

This step is purely Hal-side. No credentials yet, no customer-side clicks — you’re just declaring the customer’s existence in your fleet. Visit /clients to see the new row.


Step 2: Authorize tenant access

For each Microsoft 365 or Google Workspace tenant Acme has, you authorize Hal to read their logs.

Microsoft 365 (device code flow)

“Connect M365 for Acme”

Hal returns a short user code and a sign-in URL:

Open https://microsoft.com/devicelogin in any browser, sign in as a Global Admin for Acme’s tenant, and enter B7K9-X4M2. I’ll wait.

You open the URL in any browser, sign in with the customer’s Global Admin credentials, and type the code. Microsoft shows you the permissions Hal is requesting — four delegated scopes that let Hal do the rest of the setup on your behalf:

  • Application.ReadWrite.All
  • AppRoleAssignment.ReadWrite.All
  • DelegatedPermissionGrant.ReadWrite.All
  • Directory.Read.All

These are delegated permissions — they’re the customer admin’s permissions that Hal exercises during this single onboarding call. Hal drops the resulting token immediately after the setup is done.

Once you accept, Hal:

  1. Creates an app registration named hal-siem-log-collector in the customer’s tenant, with the full canonical permission manifest declared at creation (Portal “Configured permissions” tab shows the complete list immediately, no “Other permissions granted” overflow).
  2. Attaches 15 read-only application permissions (12 Microsoft Graph, 3 Office 365 Management API) and one delegated baseline scope (User.Read) — same shape Microsoft’s Portal “New registration” produces by default.
  3. Grants admin consent on each application permission programmatically, plus a tenant-wide consent grant for User.Read (the green-check equivalent of clicking “Grant admin consent” in the Portal).
  4. Mints a 24-month client secret with the description hal .
  5. Reads the tenant’s verified domain list from Microsoft Graph and stores them for routing.
  6. Asks you to confirm: “You signed into Acme Corporation (acmecorp.com), tenant ID abc-123. Confirm this is the correct Azure tenant?”

Confirming persists everything to Hal’s customer database. Rejecting drops the token and writes nothing — useful if you signed into the wrong tenant by accident.

End state: an app registration named hal-siem-log-collector visible in Acme’s Azure portal under Microsoft Entra → App registrations, structurally identical to what the manual guide would produce (same 15 application permissions, same User.Read delegated scope, same admin consent state, same secret description).

Google Workspace (service account and domain-wide delegation)

“Connect GWS for Acme, admin email is admin@acme.com

Hal returns paste instructions:

Open https://admin.google.com signed in as admin@acme.com, navigate to Security → Access and data control → API controls → Manage Domain Wide Delegation → Add new. Paste this Client ID: 114291782315270707603. Paste these OAuth scopes (comma-separated, no spaces):

https://www.googleapis.com/auth/admin.reports.audit.readonly,https://www.googleapis.com/auth/admin.directory.user.readonly,https://www.googleapis.com/auth/apps.alerts

Click Authorize. Reply ‘done’ when complete.

You complete the paste in Acme’s Workspace Admin Console. The Client ID is HAL AI’s fleet-wide service account — one paste authorizes Hal to act as the named admin via domain-wide delegation. No service account, GCP project, or JSON key on Acme’s side.

When you reply “done”, Hal:

  1. Calls Google’s Directory API impersonating admin@acme.com to verify the DWD paste worked.
  2. Reads the workspace’s display name and verified domains.
  3. Asks you to confirm: “DWD verified. I’m now authorized as admin@acme.com in Acme Corporation, customer ID C0xxx. Confirm this is the correct Workspace?”

Confirming persists everything. Rejecting drops without writing.


Step 3: Activate ingestion

When you’re ready for log volume to start flowing:

“Enable Acme’s M365 ingest” (or “Enable Acme’s GWS ingest”)

Hal opens the log sources, refreshes the routing rules, and the first ingest cycle (within minutes) backfills the default window — around a week for M365, four weeks for GWS.

You can see the new sources on /logs → Sources once events start flowing.


Step 4: Re-test later

Customers occasionally rotate their secrets, revoke DWD, or remove admin permissions. To check whether Hal’s stored credentials still work without re-onboarding:

“Test Acme’s M365 access”

Hal runs a live API call with the stored credentials and reports back. If something’s wrong, the error tells you exactly what happened: secret expired, app reg deleted, DWD revoked, admin demoted, etc. — with the next-step instruction.


Audit and recovery

After onboarding, Hal can audit and repair the per-customer app registration without re-onboarding from scratch. Useful when an MSP or customer admin makes an edit in the Azure Portal that drifts the app reg away from canonical state, or when a permission was missed during initial setup.

Audit a tenant’s app registration

“Audit Acme’s M365 permissions” (or “check Acme’s app registration”)

Hal queries the customer’s tenant using stored read-only credentials (no admin re-consent needed) and reports across three layers:

  • Application role grants — are all 15 canonical permissions actually granted?
  • Manifest (requiredResourceAccess) — does Portal’s “Configured permissions” tab list the canonical set?
  • Delegated baseline — is the tenant-wide User.Read consent present (the green-check on the Delegated row)?

The audit tags the drift it finds with one of: none / missing_roles_only / manifest_drift / delegated_only / extras_present / multiple — and recommends the right repair tool based on what’s actually wrong.

Light-touch repair — missing role grants only

“Repair Acme’s M365 permissions”

For drift_class: missing_roles_only. Mirrors the onboarding device- code flow: customer Global Admin signs in once at microsoft.com/devicelogin, Hal POSTs the missing role grants against the existing app registration. No new app reg, no new client secret, no Hal-side state change. Useful when Hal adds a new permission to its canonical list and existing customers need it back-filled.

Full reset — delete-and-recreate

“Reset Acme’s M365 app registration”

For any other drift class (manifest_drift, delegated_only, extras_present, or multiple) — including the cases where an MSP edited the manifest in Portal, accidentally added an over-privilege permission, deleted the User.Read consent, or the secret got re-uploaded with a non-canonical description. After a customer Global Admin signs in via device-code, Hal:

  1. DELETEs the existing app registration in the customer’s Azure tenant.
  2. Re-runs the full onboarding flow — same code path that produced the original app registration, so the end state is bit-for-bit identical to a fresh onboarding.
  3. UPSERTs the new client_id / secret / expiration in Hal’s customer database (keyed on azure_tenant_id, so the rest of Acme’s Hal state — tenant rows, log store + sources, ingest cursors, domain mappings, lookups — is preserved unchanged).

A brief gap on the next ingest cycle: any in-flight call using the old secret fails once, the next poll picks up the new secret and resumes. No data loss; ingest is at-least-once with dedup.

The reset is admin-only and requires verbal confirmation in chat before the destructive DELETE happens. Hal also checks that the admin’s device-code sign-in landed in the same tenant as the stored credentials before proceeding — protects against accidental cross-tenant resets when the admin manages several customers.


Questions? Contact us.