Universal Automation Protocol (UAP)

Info

UAP は、自動化をより分かりやすく、持ち運びやすく、将来にも対応しやすいものにします。

Universal Automation Protocol (UAP) は、あらゆる端末やプラットフォームで自動化タスクを定義・実行するために HuBrowser が作ったオープン標準です。初心者でも上級者でも、UAP を使えば、シンプルで読みやすい形式で自動化タスクを記録・インポート・エクスポートできます。UAP 対応アプリならどれでも実行できるので、特定ベンダーに縛られません。

Tip

技術知識がなくても、このページを読めば自分用の自動化ステップをかなり分かりやすく理解して書けます。 技術知識があるなら、これが企業向け UI テストやクロスプラットフォーム自動化にどうつながるかも見えてきます。

  • 人にやさしい: JSON を使うので、読み書きしやすいです。
  • 型安全: プロトコル型は TypeScript で定義されており、信頼性を高めています。
  • AI-first: モバイル AI エージェント時代を前提に設計されていて、Playwright や Selenium のような従来標準では解きにくい課題に対応します。
  • クロスプラットフォーム: プラットフォームをまたいで自動化スクリプトを共有できます。たとえ HuBrowser が iPhone をサポートしていなくても、スクリプト自体は動かせる可能性があります。

用語

  • Mode: 私たちがサポートする 3 つのモード:
    • instruction: アクションを自然言語で指示するモード。
    • recording: 録画した自動化ステップを使うモード。
    • script: スクリプト化された自動化ステップを使うモード。
  • Harden: より柔軟なモードから、より決定論的なモードへ切り替えること。たとえば instruction から script へ移ることで、自動化が速く正確になります。
  • Soften: より決定論的なモードから、より柔軟なモードへ切り替えること。たとえば script から instruction へ移ることで、適応力は上がりますが、そのぶん遅くなることがあります。

例: UAP アクション(JSON)

[
	{
		"command": "goal",
		"goal": "Submit the form"
	},
	{
		"command": "tap",
		"selector": "#submit-button",
		"displayMsg": "Tap the submit button"
	},
	{
		"command": "wait",
		"duration": 2000,
		"displayMsg": "Wait for 2 seconds"
	},
	{
		"command": "assert",
		"assertion": {
			"type": "visible",
			"selector": "#success-message"
		},
		"displayMsg": "Check if success message is visible"
	}
]

この例は、シンプルなフォーム送信ワークフローを示しています。UAP アクションは書きやすく、読みやすいのが特徴です。

自動化設定(TypeScript)

/**
 * Types for AI actions (specs only)
 * Adapt best practices from Playwright and Puppeteer for AI era
 */

// Common base for all AI actions
export interface CommonAIAction {
	/**
	 * The command to execute (e.g. 'tap', 'wait', 'open_link', etc)
	 */
	command: string
	/**
	 * Optional message to display to the user
	 */
	displayMsg?: string
	/**
	 * If true, do not wait for this action to finish before proceeding to the next task (AI era best practice)
	 * Defaults to false
	 */
	noWait?: boolean
	/**
	 * Wait strategy
	 */
	waitUntil?:
		| 'domcontentloaded'
		| 'load'
		| 'networkidle'
		| 'visible'
		| 'hidden'
}

export interface AIGoalAction extends CommonAIAction {
	command: 'goal'
	goal: string // natural language goal
}

export interface AITapAction extends CommonAIAction {
	command: 'tap'
	selector: string
}

export interface AIHoverAction extends CommonAIAction {
	command: 'hover'
	selector: string
}

export interface AIDragAction extends CommonAIAction {
	command: 'drag'
	sourceSelector: string
	targetSelector: string
}

export interface AITypeAction extends CommonAIAction {
	command: 'type'
	selector: string
	text: string
}

export interface AIKeyboardPressAction extends CommonAIAction {
	command: 'keyboard_press'
	keys: string[]
}

export interface AIScrollAction extends CommonAIAction {
	command: 'scroll'
	selector?: string
	direction: 'up' | 'down' | 'left' | 'right'
	amount?: number // pixels or percent
}

export interface AIScrollToAction extends CommonAIAction {
	command: 'scroll_to'
	selector?: string
	edge: 'top' | 'bottom' | 'left' | 'right'
}

export interface AIWaitAction extends CommonAIAction {
	command: 'wait'
	duration: number // milliseconds
}

export interface AIOpenLinkAction extends CommonAIAction {
	command: 'open_link'
	url: string
}

export interface AIZoomAction extends CommonAIAction {
	command: 'zoom'
	zoomLevel: number // e.g. 1.0 = 100%, 2.0 = 200%
	selector?: string // optional, for zooming a specific element
}

export interface AIMultitouchAction extends CommonAIAction {
	command: 'multitouch'
	events: Array<{
		type: 'pinch' | 'spread' | 'rotate' | 'swipe'
		start: { x: number; y: number }
		end: { x: number; y: number }
		fingers?: number // default 2
		angle?: number // for rotate
		amount?: number // for pinch/spread (pixels or percent)
	}>
	selector?: string // optional, for targeting a specific element
}

export interface AIGestureAction extends CommonAIAction {
	command: 'gesture'
	gestureType:
		| 'swipe'
		| 'flick'
		| 'longpress'
		| 'doubletap'
		| 'press'
		| 'pan'
		| 'rotate' // exclude 'pinch' and 'zoom' to avoid overlap
	start: { x: number; y: number }
	end?: { x: number; y: number }
	duration?: number // ms, for longpress or press
	fingers?: number // default 1
	angle?: number // for rotate
	selector?: string // optional, for targeting a specific element
}

export interface AIGoToTabAction extends CommonAIAction {
	command: 'go_to_tab'
	description: string
}

/**
 * AISetValueAction: Set the value of an input or element.
 */
export interface AISetValueAction extends CommonAIAction {
  command: 'set_value'
  selector: string
  value: string | number | boolean
}

/**
 * AIAssertAction: Assert a condition on the UI or data.
 */
export interface AIAssertAction extends CommonAIAction {
  command: 'assert'
  assertion:
	| { type: 'visible'; selector: string }
	| { type: 'not_visible'; selector: string }
	| { type: 'text_equals'; selector: string; value: string }
	| { type: 'value_equals'; selector: string; value: string | number | boolean }
}

/**
 * AIActionType: Accepts any of the known action types, or a custom command with arbitrary params.
 * This enables extension with custom commands and parameters.
 */
export type AIActionType =
	// stochastic (random) actions
	| AIGoalAction
	// deterministic actions
	| AITapAction
	| AIWaitAction
	| AIHoverAction
	| AIDragAction
	| AITypeAction
	| AIKeyboardPressAction
	| AIScrollAction
	| AIScrollToAction
	| AIOpenLinkAction
	| AIZoomAction
	| AIMultitouchAction
	| AIGestureAction
	| AIGoToTabAction
	| CustomAIAction
	| AISetValueAction
	| AIAssertAction

/**
 * CustomAIAction: Allows any string as command and arbitrary params.
 */
export interface CustomAIAction extends CommonAIAction {
	command: string // any string
	[name: string]: any // allow arbitrary params
}

構造制御の基本

UAP は、分かりやすく拡張しやすい定義を保つために、見慣れた schema 概念を使います。

  • properties: オブジェクトの属性を定義します。
  • anyOf: 複数の型や構造を許可します。
  • required: 必須フィールドを指定します。
  • type: 値のデータ型を制限します。
  • default: 既定値を与えます。
  • item_count_range: 配列の最小長と最大長を制御します。

ツール利用

UAP では、ツール呼び出しや function call も構造化して表現できます。

{
	"tool_choice": { "function": { "name": "" } },
	"tools": [
		{
			"function": {
				"description": "",
				"name": "",
				"parameters": {}
			},
			"type": "function"
		}
	]
}

この構造により、UAP でツールや関数をどう記述するかが定義されます。

保守とバージョニング

  • version: v25.1
  • オープンソースライセンス: Apache License 2.0
  • AI は速く進化しますが、変更はできるだけ予測しやすく保つようにしています。
    • 大きな破壊的変更は多くても 2 か月に 1 回まで。その際は自動化プロトコルファイルを再ダウンロードする必要があります。
  • Graceful fallback: ある環境が特定のアクションをサポートしていない場合でも、UAP 対応アプリは自動化が予想外に壊れないよう配慮すべきです。