Tutorial: build a browser-automation Digital Human
Tutorial: turn Halo's OA approval sample into a Digital Human that works in a web system you sign in to, with bundled browser scripts, memory and safe defaults.
In this tutorial you adapt a sample into a Digital Human that works inside a web system you sign in to. The sample is an approval assistant for an office system: every 30 minutes it lists your pending approvals, handles the ones that match your rules, and reports the rest. Along the way you meet every part of a production Digital Human: the spec, bundled browser scripts, memory, a login, and a safe default.
Before you start
- Halo with an AI model set up.
- A web system you sign in to in a browser, such as an approval, ticket or CRM system, whose pages you can inspect with the browser's developer tools.
- Some JavaScript, if you want to adapt the scripts by hand. Halo can also adapt them for you.
1. Download the sample
Download oa-approval-agent.zip and unzip it into your workspace folder:
oa-approval-agent/
├── spec.yaml the Digital Human
├── README.md
└── skills/
├── oa-todo-list/ script: list pending approvals
├── oa-approve/ script: approve or reject one
└── oa-approved-list/ script: list approved items, to double-checkThe sample does not run as it is
Its addresses, API paths and field names are placeholders such as your-oa.example.com. You replace them with your system's in step 4.
2. Read the spec
Open spec.yaml. Five parts matter:
requires.skillslists the three scripts as bundled skills, so they are installed with the Digital Human into its workspace's.claude/skills/, the paths the prompt'sbrowser_runcalls use.system_promptis a procedure: a list of forbidden actions, then numbered steps that each name the exact call, such asbrowser_run({ file: ".claude/skills/oa-todo-list/index.js", params: { pageSize: 30 } }), and what to do when it fails. The last step reports withreport_to_user.config_schemais the settings form.auto_approveis abooleanthat defaults tofalse, so the Digital Human only reports until you turn it on.max_approvals_per_runcaps how many it may handle in one run.memory_schemakeepsprocessed_todos, so an item is never handled twice, plus the time of the last run and running totals.browser_loginnames the system's address, so Halo asks you to sign in there.
Each field is described in the spec reference.
3. Read a browser script
Open skills/oa-todo-list/index.js. It is one async (params) => { … } function that runs inside the signed-in page:
async (params) => {
const { pageSize = 30 } = params || {}
try {
const resp = await fetch(`https://your-oa.example.com/api/todo/list?pageSize=${pageSize}`, {
credentials: 'include',
headers: { Accept: 'application/json' },
})
if (!resp.ok) {
return { success: false, status: resp.status, error: resp.status === 401 ? 'not logged in' : `HTTP ${resp.status}` }
}
const data = await resp.json()
return { success: true, todos: data.list ?? [] }
} catch (e) {
return { success: false, error: e.message }
}
}The script calls the system's own API with the session you signed in with, and it never throws: every outcome comes back as { success, … }, so the prompt can tell "not logged in" from other failures. This is shortened from the file; the full rules are under Browser scripts.
4. Adapt it to your system
Find the requests your system makes. Sign in to it in a browser, open the developer tools on the Network tab, filter for Fetch/XHR, and approve or reject one item. Note each request's URL, method, body and the fields of its response.
Then adapt the package in one of two ways:
- Let Halo do it. In a conversation in this workspace, say: "Adapt the Digital Human in the oa-approval-agent folder to our approval system at
<YOUR_SYSTEM_URL>. The list of pending items comes from<LIST_REQUEST>and approving one sends<APPROVE_REQUEST>. Update the three scripts,browser_loginand the address in the first step ofsystem_prompt, and keep the rest of the spec." - By hand. In each
index.js, replace the base address, the API paths and the field names. Inspec.yaml, setbrowser_login[].urland the address in the first step ofsystem_prompt.
If an action needs a token from the page, such as a CSRF token in a form field, have the script read it from the page before it calls the API.
5. Import it and sign in
- In Halo, open Digital Humans, click Create Digital Human, choose Import, and drop the
oa-approval-agentfolder (or a.zipof it). Import installs the bundled scripts along with the Digital Human. - Open the new Digital Human, go to Capabilities and settings, and fill in the keyword settings. Leave
auto_approve(labelled 自动审批 in the sample) off. - Above the Digital Human's Work activity, click Open to log in for your system and sign in.
6. Test it
- Click Run now on the Digital Human's page.
- Open Work activity and read the run's report. With
auto_approveoff it only suggests: it lists what it would approve and reject, and changes nothing in your system. - If the report says it is not logged in, sign in again with Open to log in. If a script fails, its error is in the report; debug it as described under Develop and debug a script.
- When a few reports match what you would have decided, narrow the keywords to a small, safe set and turn
auto_approveon.
Done
The Digital Human now checks your system every 30 minutes on its own, handles only items that match your rules, never more than max_approvals_per_run at once, and reports the rest to you.
7. Share it
In the desktop app, on the Digital Human's page, click ⋮ › Share › Export to get a .dhpkg package, or submit it to a Store, where it is listed after review. See Publish to the Store. Remove company addresses and names before you share it outside your company.
Troubleshooting
| What you see | What to do |
|---|---|
| The report says the OA login has expired (HTTP 401) | Sign in again with Open to log in. Sessions expire on the system's side |
Path not allowed | The script is outside the workspace and its .claude/skills/ folder. Import the package with Create Digital Human › Import so the skills land in the workspace |
| The Digital Human doesn't run on its own | Check subscriptions (the sample runs on every: "30m") and that it isn't paused. Scheduled runs are also skipped while one of its questions is unanswered, such as its request to sign in again: answer it in Work activity |
| Items are handled twice | The last step must write the handled ids into memory before the report |
Next steps
- Production-grade Digital Humans: prompts, memory and scripts that hold up
- Digital Human spec reference: every field
- DHP protocol: how a package is laid out