---
title: "Build a Slack Help Desk with Notion Custom Agents"
description: "Connect Slack to Notion Custom Agents and build an answer library from pages your team trusts, with source lines, honest refusals, and a human queue."
canonical: "https://adamtheautomator.com/build-a-slack-help-desk-with-notion-custom-agents/"
---

# Build a Slack Help Desk with Notion Custom Agents

> Connect Slack to Notion Custom Agents and build an answer library from pages your team trusts, with source lines, honest refusals, and a human queue.

Source: https://adamtheautomator.com/build-a-slack-help-desk-with-notion-custom-agents/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Build a Slack Help Desk with Notion Custom Agents](https://adamtheautomator.com/wp-content/uploads/publisher/3f25d9c85b2b813e8a0dea451dc89138/6fb0067ffdaeca7dafae4e68bbfde0f73ea197247f36bcc3d64e68dd24a4df0d.webp)

# Build a Slack Help Desk with Notion Custom Agents

[![](https://secure.gravatar.com/avatar/d0b9d42e21e5622713f8b693aa5c0f9244d5f7dd200ed29b8398f52dee5de337?s=192&d=mm&r=g)Adam Bertram](https://adamtheautomator.com/author/adam-bertram/)29 October 202614 min. read

Categories: [AI Agents](/category/ai-agents/)

Tags:[Slack](/tag/slack/)[Notion](/tag/notion/)[AI](/tag/ai/)[Automation](/tag/automation/)

Table of Contents

*   [Prerequisites](#prerequisites)
*   [What You Need on Both Sides](#what-you-need-on-both-sides)
*   [Version and Credit Model](#version-and-credit-model)
*   [The Build Order Matters More Than Any Setting](#the-build-order-matters-more-than-any-setting)
*   [Connect Slack Before You Turn On a Trigger](#connect-slack-before-you-turn-on-a-trigger)
*   [Channel Membership Is Not a Security Boundary](#channel-membership-is-not-a-security-boundary)
*   [Build the Answer Library from Pages You Already Trust](#build-the-answer-library-from-pages-you-already-trust)
*   [What Earns a Row](#what-earns-a-row)
*   [Write Instructions That Cite Sources and Refuse to Guess](#write-instructions-that-cite-sources-and-refuse-to-guess)
*   [Audit the Answers You Cannot Read](#audit-the-answers-you-cannot-read)
*   [Open a Human Queue for Unanswered Questions](#open-a-human-queue-for-unanswered-questions)
*   [The Shape of the Queue](#the-shape-of-the-queue)
*   [Prove the Row Lands](#prove-the-row-lands)
*   [Test It Three Ways Before You Publish](#test-it-three-ways-before-you-publish)
*   [The Matrix](#the-matrix)
*   [After the Three Tests Pass](#after-the-three-tests-pass)
*   [Meter Credits Before You Widen the Trigger](#meter-credits-before-you-widen-the-trigger)
*   [What a Run Costs](#what-a-run-costs)
*   [Measure Your Own Ratio](#measure-your-own-ratio)
*   [What This Slack Help Desk Is Not](#what-this-slack-help-desk-is-not)
*   [The Question That Started This](#the-question-that-started-this)

Suppose the same question has landed in your #help channel four times this month.

The person who answered probably typed it from memory, five minutes after a meeting, while the approved page sat three searches away. Next month someone else answers it differently, and nobody can point at the page that settles the argument. A [Notion Custom Agent](https://www.notion.com/help/custom-agents) can answer that channel from documentation you have approved, with a link back to the page it used. You will connect Slack to the Notion workspace, build a small answer library from pages your team already trusts, write instructions that force a source line and an honest “I don’t know,” and open a queue a human owns. Then you will test it three ways before the bot speaks in a real channel. The result is a help desk that shows its work and stops when the evidence runs out.

## Prerequisites

Everything below assumes one Notion workspace and one Slack tenant you can change yourself.

### What You Need on Both Sides

If you want to follow along hands-on, you’ll need:

*   A Business or Enterprise Notion workspace, because Custom Agents are not included on Free or Plus and Business lists at $20 per member per month ([Notion pricing](https://www.notion.com/pricing)).
    
*   A Slack workspace owner, or a person approved to connect external apps, since the Slack connection can only be made by someone who owns both workspaces ([Notion AI connector for Slack](https://www.notion.com/help/notion-ai-connectors-for-slack)).
    
*   The same email address on both accounts. Notion asks you to connect the Slack app even if you already use Slack elsewhere in Notion, and the connection expects that shared address ([Custom Agents](https://www.notion.com/help/custom-agents)).
    
*   Permission to create Custom Agents, because workspace owners can limit creation to owners or named groups ([sharing and permissions](https://www.notion.com/help/custom-agents-sharing-and-permissions)).
    
*   Standard and Select credits, the two pools a seat draws on. Business and Enterprise seats include 1,500 Standard and 500 Select credits per month, and [how AI credits work](https://www.notion.com/help/how-ai-credits-work-for-custom-agents) explains which pool an agent spends first.
    
*   Explicit access to the demo pages and databases. An agent starts with access to nothing until you grant it.
    
*   A test channel you own, plus your own Slack authorization if that channel is private.
    

### Version and Credit Model

This guide targets Notion 3.8 (October 13, 2026), the current numbered release, and the Standard and Select credit model that arrived October 19, 2026, with existing workspaces moving November 2, 2026. Custom Agents shipped in Notion 3.3 (February 24, 2026), where they ran on purchased Notion credits rather than Standard and Select. Check your workspace’s release notes and credit dashboard before you follow along, because both change between releases.

## The Build Order Matters More Than Any Setting

A Custom Agent answers a Slack message only after the workspace connection, the library access, and the instructions exist, and the trigger goes on last. Notion draws the product line itself, stating that “Notion Agent is on-demand, whereas Custom Agents are autonomous” ([Custom Agents](https://www.notion.com/help/custom-agents)). The on-demand version acts as you. The autonomous one acts as itself, on access you granted, which is why the sequence below exists.

1.  Create `#help-desk-test` and invite the three to five people who will run the tests.
    
2.  Connect Slack to the Notion workspace from Notion, as a workspace owner.
    
3.  Build the `Help Desk Answers`, `Approved Sources`, and `Unresolved Questions` databases, and approve 10 to 20 answers.
    
4.  Write the instructions, then attach the databases under **Tools and access**.
    
5.  Connect the agent to exactly one channel.
    
6.  Run manual tests in the agent’s **Chat** tab.
    
7.  Add a mention-only Slack trigger under the agent’s **Triggers**.
    
8.  Run the three tests below, then widen.
    

Notion’s best-practices page asks for the same patience, running the agent manually, reviewing the output, and turning on triggers only once results look right ([best practices](https://www.notion.com/help/best-practices-for-creating-and-optimizing-a-custom-agent)).

## Connect Slack Before You Turn On a Trigger

The Slack connection starts in Notion. A workspace owner opens **Settings** → **Notion AI**, clicks **+** next to **Slack**, and finishes the flow in the Slack workspace the agent will serve. On Enterprise Grid, confirm the correct workspace before choosing channels ([connector documentation](https://www.notion.com/help/notion-ai-connectors-for-slack)). Start from Slack instead and you get a connection that cannot see the channels you need.

The workspace connector chooses all public channels or a named list, with an option to include public channels created later. The agent’s own Slack connection chooses which of those channels it reads and where it replies. A private channel adds your personal Slack authorization on top.

| Dimension | Public channel | Private channel |
| --- | --- | --- |
| Connected by | Workspace connector, all or selected channels | The individual member, from their own Slack account |
| Extra Slack authorization | Not required | Required, per person |
| Slack Connect channels with external users | Excluded from the indexed dataset | Excluded from the indexed dataset |
| Who sees the agent’s replies | Anyone in the channel | Anyone in the channel, plus anyone with access to the agent |

That exclusion covers what the connector indexes, and a guest cannot use the connection at all. Notion AI can still use Slack Connect content in a real-time answer when the asking user has access to it, and there is no way to leave Slack Connect channels out of those real-time results.

Slack’s permission model explains the private row. An app reads public-channel messages only after it is added, private-channel history needs `groups:history` plus a bot that is a member of that channel, and posting needs `chat:write` in an approved channel or `chat:write.public` for public channels only ([Slack scopes](https://api.slack.com/scopes)). Add the agent from the channel’s **Agents & apps** tab ([Slack’s agent guide](https://slack.com/help/articles/33076000248851-Work-with-AI-agents-in-Slack)). For @mention triggers, a workspace owner must first allow members to create user groups, because Notion’s mention trigger depends on that Slack setting ([Slack user groups](https://slack.com/help/articles/212906697-Create-and-edit-user-groups)).

The trigger itself lives in the agent’s **Settings**. Choose **Triggers**, add a **Slack** trigger, pick the channel to watch, and set the event to the agent being mentioned in a message. Confirm the trigger reads as mention-only before you save, because a message trigger on a busy channel turns every side conversation into a paid run ([Slack trigger setup](https://www.notion.com/help/custom-agents)).

* * *

_**Warning: Turning on the trigger before the channel authorization is finished produces the worst test result, an agent that looks broken. The trigger fires, the agent reads nothing, and you spend the afternoon rewriting instructions that were never the problem.**_

* * *

### Channel Membership Is Not a Security Boundary

What surprises people coming from on-demand AI is that the agent answers with its own permissions. Notion’s sharing documentation states, “A Custom Agent responds using the agent’s own access, not the permissions of the person who triggered it,” and adds that agent users “can retrieve information from resources they lack access to” ([sharing and permissions](https://www.notion.com/help/custom-agents-sharing-and-permissions)). Anyone with access to the agent can see its outputs even without access to the underlying Slack private channel.

The answer library is the only boundary between a confidential channel and the rest of the workspace, because the agent answers from its own access. Keep that in mind when someone asks you to add a confidential channel to a public help desk.

One timing detail catches every pilot. The first Slack backfill covers one year of messages and can take up to 36 hours, and new messages can take up to three hours to index ([connector documentation](https://www.notion.com/help/notion-ai-connectors-for-slack)). Judge the agent on day three, not on the afternoon you connected it.

## Build the Answer Library from Pages You Already Trust

Start with the questions people ask every week, not every page in the workspace. Pick 10 to 20 and give each one a record. Notion’s guidance is to start with one channel instead of five and widen once output is consistent ([best practices](https://www.notion.com/help/best-practices-for-creating-and-optimizing-a-custom-agent)).

The property list below is enough to rebuild both databases in Notion’s database builder.

```text
Help Desk Answers
  Question       Title
  Answer         Rich text, or the page body for long answers
  Status         Select: Approved | Draft | Retired
  Owner          Person
  Approved on    Date
  Source page    Relation to Approved Sources
  Visibility     Select: All staff | Team only
  Channel        Select: help-desk-test

Approved Sources
  Page           Title, with the link stored in the page
  Owning team    Select
  Reviewed on    Date
```

`Approved Sources` holds one row per canonical page, and every answer points at one. That relation makes “the answer has a source” mechanically checkable during review. A row with no source is a library defect, and the agent should refuse it rather than improvise a citation.

### What Earns a Row

A question earns a row only when it repeats often, it is policy-shaped rather than judgment-shaped, and an approved page already answers it. “What is the parental leave policy” belongs. “Should we take this customer” does not, because no approved page settles it and the model will produce something that sounds like a decision.

`Status` is the only gate the agent trusts. `Draft` rows are the review pipeline. `Retired` rows keep the audit trail for “we used to say X” without letting the old answer back into Slack. Retire answers instead of deleting them. The diagram below traces both paths a question can take: an approved answer with a source line, or a queue row when no approved answer exists.

![Answer routing paths](https://adamtheautomator.com/wp-content/uploads/publisher/37a92f4bc3ae5a5ec5a4139579c6c31c4253a3fc314dd557528f922ef96ff7c3.jpg)

## Write Instructions That Cite Sources and Refuse to Guess

Notion does not ship a switch that forces citations in Slack replies. Every answer carrying a source is an instruction you write and an audit you run, which is why a week of hunting through settings will find nothing.

The instruction block names the channel, the status filter, the source line, and the refusal path.

```text
You are the help desk for #help-desk-test.

Answer only from Help Desk Answers records whose Status is Approved
and whose Visibility matches the channel you are answering in.

End every answer with one source line:
Source: <page title> <Notion link from the Source page relation>

Use one source per factual claim. If two approved records disagree,
say the documentation is inconsistent, do not pick one, and file the
question in Unresolved Questions.

If no approved record supports an answer, or the question is about
people, pay, or legal matters, do not guess and do not search the web.
Reply with the unknown-answer response and create one row in
Unresolved Questions.

Never quote a record with Visibility set to Team only in a public
channel. Never answer from a Draft or Retired record.
```

The source line turns review into a five-second check. Open the thread, click the link, confirm the page says what the bot said. Without it you are grading prose, and prose always sounds confident.

Turn **Web access** off. Notion documents it as a per-agent toggle and recommends keeping it off for strictly internal workflows ([web access setting](https://www.notion.com/help/custom-agents)). Then attach the databases under **Tools and access**: `Help Desk Answers` and `Approved Sources` at **Can view**, `Unresolved Questions` at **Can edit**. Linking a page inside Instructions does not add it there, and the failure looks like the agent refusing a page you just linked.

### Audit the Answers You Cannot Read

The **Activity** tab logs every run, what triggered it, the steps taken, and any errors. Read it for the runs whose source line points somewhere unexpected, because a plausible link to the wrong page is the most common grounded-answer failure.

Insights exports a CSV capped at 300 chats for the selected period on Business and Enterprise plans ([CSV export limits](https://www.notion.com/help/custom-agents)). Sample 30 answers a week and check two things, whether the link resolves and whether that page supports the claim. [Business plans](https://www.notion.com/pricing) also include “Verify any page,” a badge for pages that are up to date, and Notion lists it as surfacing in AI citations. Put that badge on the ten answers people ask about most.

* * *

_**Pro Tip: Write instructions as imperatives and keep them short. Notion’s guidance is to describe the outcome and the format, name the edge case, and expect several iterations before the agent behaves.**_

* * *

## Open a Human Queue for Unanswered Questions

The unknown-answer path separates a demo from a help desk. A bot that guesses gets trusted once. A bot that says it has no approved answer hands you a list of documentation gaps, which is the useful product of the first month.

### The Shape of the Queue

Status, owner, and a due date are what make a database a queue instead of a complaint folder. Those three properties follow the normal [Notion database property model](https://www.notion.com/help/database-properties), so the schema below is a plain table with a select, people, date, and relation:

```text
Unresolved Questions
  Question        Title (verbatim wording from Slack)
  Asked by        Person
  Channel         Select: help-desk-test
  Asked at        Created time
  Status          Select: New | Triaged | Waiting on requester | Answered | Closed
  Owner           Person, left empty by the agent
  SLA due         Date, calculated from Asked at
  Slack thread    URL
  Linked answer   Relation to Help Desk Answers
  Agent run       URL or text pointing at the Activity entry
```

The agent creates the row with `Status` set to `New`, fills in the question, asker, channel, time, and thread link, and leaves `Owner` empty. A human triages it, assigns an owner, and sets the response window behind `SLA due`. The Slack reply names the queue and links the row, never a person, because a bot that names someone creates an ownership gap the moment that person is on holiday.

### Prove the Row Lands

Confirm the row appears in your own workspace. Notion documents agents taking actions such as filing bugs and updating records, and it documents Can edit grants, but no page promises the exact record-creation behavior for an editable database. Treat it as observed behavior. If nothing appears, name the database explicitly in the instructions and re-run the test.

* * *

_**Warning: A triggered agent sometimes declines to reply or times out before sending, and the “Working on it…” indicator then disappears. Silence is documented, so give the queue owner a daily sweep of threads that got the indicator and no answer.**_

* * *

Every triaged question that produces a good answer becomes a new `Help Desk Answers` row with an approved status and a source relation. That loop grows the library without anyone writing a knowledge management strategy.

## Test It Three Ways Before You Publish

Run each test from Slack as a non-owner. An owner sees more than a regular member, so an owner-run test proves less than it appears to.

### The Matrix

| Test | Setup | Pass looks like | Fail signal |
| --- | --- | --- | --- |
| Known answer | One approved row, “How do I request a new laptop,” pointing at the IT hardware page | Correct answer, source link resolves to that page, no invented steps | Right answer with no link, or a link to a draft row |
| Unknown answer | A question with no approved row, “What is our sabbatical policy” | Explicit “no approved answer” reply, one queue row with status New and no owner, queue link in the thread | A guess, a web-sourced answer, or silence |
| Restricted information | One approved row with visibility set to Team only, holding a harmless canary such as a fictional salary band | Agent declines, offers the unknown-answer path, canary absent from the channel, the queue row, and any log excerpt | Canary in the channel, a paraphrase of the row, or “I can’t share that” plus enough detail to reconstruct it |

The third test is the one teams skip and the one that matters. Notion documents that agent users can retrieve information from resources they do not have access to, and that anyone with access to the agent sees its outputs regardless of Slack channel access ([sharing and permissions](https://www.notion.com/help/custom-agents-sharing-and-permissions)). Without the canary, the boundary between a team-only row and a public channel rests on hope instead of evidence.

If the canary appears, do not rewrite the instruction and retry. Remove the restricted row from the agent’s access and rebuild the boundary, because an instruction that lost that argument once will lose it again on a question you did not think to test.

The illustration below shows each test in its passing form. A sourced answer lands in the thread, an honest refusal arrives with a linked queue row, and the canary never reaches the channel.

![Three test outcomes](https://adamtheautomator.com/wp-content/uploads/publisher/58973e7dd76a38f8b07819b9eb9fbae4867d3f8fadfbaa7ecbda9a7546bf6884.jpg)

### After the Three Tests Pass

Once the three Slack tests pass, check the behaviors that break in production. Trigger inside a thread and confirm the reply lands there. Post an unrelated message with a keyword filter and confirm nothing fires. An emoji reaction can also start a run instead of a mention, which suits a channel where people already react to questions; this build stays on mentions because a reaction on a side conversation costs the same as a real question. Duplicate the agent and confirm the copy has no Slack connection, since duplicates start private and do not inherit tool connections ([duplicating an agent](https://www.notion.com/help/custom-agents)). Re-run the three tests after every instruction change, with version history as the rollback path.

## Meter Credits Before You Widen the Trigger

The published numbers tell you what a run might cost. Only your own pilot tells you what it does cost.

### What a Run Costs

A help desk answering 40 questions a day is cheap until it is not, and Notion publishes no single per-run price, but it does publish [per-use-case cost ranges](https://www.notion.com/help/buy-and-track-notion-credits-for-custom-agents): a Q&A agent answering internal policy and how-to questions in Slack runs about $0.03-$0.11 per run, roughly 90-333 runs per 1,000 credits (per $10), and the page states that actual usage depends on how often the agent runs, how many steps it takes, and which model it uses. Notion also publishes the allocation each seat draws on. An agent spends the owner’s Select credits first, then the owner’s allowance, then workspace credits if an admin allows it ([how AI credits work](https://www.notion.com/help/how-ai-credits-work-for-custom-agents)). It pauses when the owner’s Select credits and any additional owner allowance are exhausted and no workspace Notion credits are available or allowed, until credits reset or workspace credits are added.

Extra credits list at $10 per 1,000 monthly Notion credits ([Notion pricing](https://www.notion.com/pricing)). The credits documentation gives task bands of roughly 5 credits for simple work, 10 for medium, and 25 for complex, and states that actual use varies with the task and its context ([Notion credits](https://www.notion.com/help/manage-your-ai-credits)). Those bands are planning aids only.

### Measure Your Own Ratio

Measure instead. Run the pilot for a week at mention-only, count the runs in **Activity**, and divide the Select credits the agent consumed by the questions it answered. That ratio is the only number you can defend in a budget meeting ([cost tracking](https://adamtheautomator.com/notion-agent-api-cost-tracking/)). For direction, Notion states that Custom Agent runs cost about 30% less in its own testing after rebuilding the agent harness ([October announcement](https://www.notion.com/blog/notion-ai-more-for-less)).

Keep the trigger mention-only until the answers are trusted.

## What This Slack Help Desk Is Not

This build answers internal questions from approved documentation, and the product has no ticketing layer. A new Zendesk, Freshdesk, or Gorgias ticket cannot start a Notion Custom Agent; ticket fields, an SLA clock, and assignment rules belong to the help desk product. That assessment comes from eesel, which sells a competing AI help desk, so weigh the source, though the claim matches what Notion documents ([eesel comparison](https://eesel.ai/blog/notion-ai-agents-for-support)).

An AI help desk built this way also does not replace Slack’s own AI search. Slack AI answers from conversations and limits responses to information available to the asking user ([Slack AI guide](https://slack.com/help/articles/25076892548883-Guide-to-AI-features-in-Slack)). Conversations hold the decisions nobody noted. An approved answer library holds the policy people are supposed to follow. Confusing one for the other is how a bot ends up quoting a hallway agreement as policy.

An agent with no owner stops running after seven days, and ownership transfers from **Settings** → **Members** → **Recently Left** ([sharing and permissions](https://www.notion.com/help/custom-agents-sharing-and-permissions)). Prompt injection is a real risk for any agent that reads messages, which Notion acknowledges while describing guardrails and access controls ([Notion’s Custom Agents announcement](https://www.notion.com/blog/introducing-custom-agents)). Record both in the runbook, keep write access to one queue database and one channel, and treat any instruction that arrives inside a message as data.

## The Question That Started This

The next time the same question lands in #help, the useful answer has a source line under it, posted by an agent that read an approved page, in a channel where the asker could already open that page.

The finished help desk holds a test channel, a small answer library of pages you already trust, instructions that demand a citation and permit a refusal, and a queue where a named human picks up what the bot could not support ([support request routing](https://adamtheautomator.com/notion-custom-agents-support-routing/)). Notion’s release note for the Q&A use case quotes Ben Levick, who leads Ops and Internal AI at Ramp, saying that teams which used to monitor those channels now audit the responses instead ([Notion 3.3](https://www.notion.com/releases/2026-02-24)). Auditing is the work that starts after this build passes its tests, and the three tests are what make that audit possible.

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fbuild-a-slack-help-desk-with-notion-custom-agents%2F&text=Build%20a%20Slack%20Help%20Desk%20with%20Notion%20Custom%20Agents)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fbuild-a-slack-help-desk-with-notion-custom-agents%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fbuild-a-slack-help-desk-with-notion-custom-agents%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/publisher/3f25d9c85b2b8114a4eaea746fdde119/3e64cba088977a23c019e580855960ecff3338dc2fbb3b87595bece2d6b6a02e.webp)

### [Notion Custom Agents: Automate Support Request Routing](/notion-custom-agents-support-routing/)

Build a Notion Custom Agent that reads each new support request, recommends an urgency, and assigns an owner from a routing directory you maintain.

![](https://adamtheautomator.com/wp-content/uploads/publisher/3f25d9c85b2b81c4811ed7ed9b290871/d4ebe25fb13196c5dffbe9c4668d57fe178690406552541f4e2f3828e040cc6f.webp)

### [Notion Custom Agents: Automate Your Weekly Project Report](/notion-custom-agents-weekly-report/)

Build a Notion Custom Agent that writes a dated weekly project report from your task database, then test it against an empty week and a repeat run.

![](https://adamtheautomator.com/wp-content/uploads/publisher/3f25d9c85b2b81c28cc6c39755dac3c7/423d6296450a064f65dba039d6aec0339ac2ba3b86b2f0ef3706c81ff1e57223.webp)

### [Notion Automation: Pick the Right Tier Every Time](/notion-automation-agents-vs-workers/)

Pick the right Notion automation tier: compare database automations, Custom Agents, and Workers, and split ticket routing to cut credit costs.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
