6.7 ИИ-агенты и агентные системы
Обзор и мотивация
ИИ-агент это большая языковая модель (LLM), обёрнутая в цикл: ей дана цель, она может вызывать инструменты, хранит некоторую память о сделанном и сама решает следующий шаг, пока цель не достигнута или она не сдаётся. Этот цикл и есть вся разница между агентом и простыми вызовами «промпт-ответ» из главы 6.3. Один вызов отвечает на вопрос. Агент читает свою почту, ищет в базе данных, заводит заявку, проверяет результат и пробует снова. Модель больше не просто производит текст; она выбирает действия в ваших системах.
Этот сдвиг меняет инженерную проблему. Когда модель лишь пишет слова, плохой вывод это плохое предложение. Когда модель управляет инструментами, плохой вывод может отправить неверное сообщение, удалить запись или перевести деньги. Поэтому интеллектуального агента лучше всего понимать как недоверенного планировщика внутри доверенной системы, а большая часть вашей работы уходит на ограничение того, что этому планировщику позволено делать. Эта глава прямо опирается на основы LLM из главы 6.3, вопросы доверия и подотчётности из главы 6.5 и платформенные практики из главы 6.6.
Для больших команд ставки организационные не меньше технических. Корпорации хотят агентов, подключённых к реальным внутренним системам (заявки, финансы, записи клиентов), а значит агенты наследуют реальный контроль доступа и реальные обязательства управления изменениями. Государство добавляет публичную подотчётность: автономное действие, затрагивающее гражданина, должно быть объяснимым, поддающимся надзору и проверяемым постфактум. Шаблон мощный. Развёрнутый без дисциплины, он быстрый способ автоматизировать ошибки.
Ключевые принципы
- Агент это модель плюс цикл, инструменты, память и цель. Риск живёт в цикле, а не прозе.
- Ограничивайте автономию задачей. Давайте наименьшее количество свободы, которое выполняет работу.
- Предпочитайте фиксированный рабочий процесс, когда шаги известны. Тянитесь к неограниченной автономии, только когда они неизвестны.
- Воспринимайте каждый инструмент как поверхность атаки и давайте ему наименьшие привилегии, с которыми он может работать.
- Ставьте человека в контур для значимых или необратимых действий и делайте отмену дешёвой.
- Оценивайте по успеху задачи, а не по тому, как читается запись.
- Трассируйте каждый запуск. Действие, которое нельзя реконструировать, действие, которым нельзя управлять.
- Простейший проект, который работает, обычно и правильный. Нередко это вообще не агент.
Рекомендации
Начинайте с рабочего процесса, добавляйте автономию только где должны
Самая частая ошибка тянуться к автономному агенту, когда хватило бы фиксированного конвейера. Если вы уже знаете шаги (извлечь поля, проверить их, найти запись, составить ответ), запишите это как оркестрируемый рабочий процесс, где модель заполняет конкретные места. Автономия оправдывает себя, когда путь действительно нельзя определить заранее, например открытое исследование или сортировка по множеству возможных инструментов. Ограничивайте автономию задачей: ограничьте число шагов, сузьте набор инструментов до нужного для этой цели и задайте ясное условие остановки. Хорошее правило давать модели ровно столько свободы, сколько требует проблема, и ни на градус больше.
Сделайте использование инструментов основной возможностью и сделайте его безопасным
Использование инструментов (также вызов функций) превращает модель в агента. Определяйте каждый инструмент точной схемой, проверяйте каждый аргумент, который предоставляет модель, и применяйте принцип наименьших привилегий: агент отчётности только для чтения получает учётные данные только для чтения, никогда доступ на запись, которым он мог бы злоупотребить. Запускайте инструменты внутри песочницы, чтобы плохой вызов не мог выйти за свой радиус поражения. Предпочитайте много узких инструментов одного назначения нескольким широким, потому что узкий инструмент легче осмыслять, наделять разрешениями и проверять. Это та же сдержанность, к которой глава 6.3 призывает для использования инструментов LLM, сделанная центральной.
Используйте явные шаблоны рассуждения и планирования
Агенты работают лучше, когда их мышление структурировано. В шаблоне «рассуждать и действовать» (популяризированном исследованием ReAct) модель чередует рассуждение о ситуации и действие, затем наблюдает результат, прежде чем рассуждать снова. Для более трудных целей пусть модель сначала планирует (раскладывает на подзадачи), а затем исполняет, чтобы вы могли просмотреть и даже утвердить план до запуска любого инструмента. Держите эти циклы наблюдаемыми и прерываемыми. План, который вы можете прочесть, план, который вы можете остановить.
Держите людей в контуре для значимых действий
Решайте на инструмент и действие, может ли модель действовать одна или должна сначала спросить. Обратимые малоценные действия (поиск, составление черновика) могут идти без присмотра. Значимые или необратимые (отправка внешних коммуникаций, перевод денег, изменение производственных данных, решение дела гражданина) нуждаются в барьере человека в контуре с реальными полномочиями сказать «нет». Проектируйте обратимость везде, где можете: предпочитайте постановку изменения в очередь его фиксации и делайте отмену первоклассной функцией, чтобы ошибочное действие стоило минут, а не инцидента.
Воспринимайте модель безопасности как состязательную
Агенты расширяют поверхность атаки, описанную в главе 4.2. Главная угроза внедрение через промпт: вредоносные инструкции, спрятанные в веб-странице, документе или письме, которые агент читает и выполняет. С ней тесно связана проблема запутавшегося заместителя (confused deputy), когда атакующий обманом заставляет привилегированного агента злоупотребить собственным законным доступом, например вывести данные через инструмент, который агенту разрешено вызывать. Предполагайте, что любое содержимое, которое агент принимает, может быть враждебным. Отделяйте доверенные инструкции от недоверенных данных, ограничивайте инструменты так, чтобы захваченный агент не мог достичь чувствительных систем, и никогда не позволяйте сырому выводу модели запускать необратимое действие без проверки.
Оценивайте по успеху задачи и тестируйте регрессию недетерминизма
Судите агентов по тому, выполняют ли они задачу, а не по тому, звучит ли запись умно. Стройте набор оценки репрезентативных целей с проверяемыми критериями успеха (получила ли заявка верный приоритет, соответствовал ли возврат политике) и запускайте его на каждое изменение промпта, модели или инструмента. Поскольку агенты недетерминированы, один проход доказывает мало: запускайте каждый случай много раз и отслеживайте долю успеха, а не «прошёл или нет». Это расширяет дисциплину офлайн- и онлайн-оценки глав 6.3 и 6.2 (инженерия машинного обучения и MLOps) на системы, чей вывод последовательность действий.
Инструментируйте запуски для наблюдаемости, стоимости и обработки отказов
Нельзя управлять тем, чего не видишь. Трассируйте каждый запуск агента от конца до конца (глава 6.6): цель, каждый шаг рассуждения, каждый вызов инструмента с его аргументами и результатом, потраченные токены и итоговый результат. Эта трассировка ваш отладчик, ваш след аудита и ваш счётчик стоимости одновременно. Задавайте жёсткие бюджеты на шаги, время и расходы, потому что агент, зацикливающийся, может быстро сжечь задержку и деньги. Обрабатывайте отказ явно: повторяйте переходные ошибки инструментов с задержкой, но обнаруживайте циклы, где модель повторяет проваливающееся действие, и отказывайте безопасно, а не барахтайтесь.
Компромиссы: плюсы и минусы
| Выбор | Плюсы | Минусы | Лучше всего, когда |
|---|---|---|---|
| Фиксированный рабочий процесс (модель заполняет места) | Предсказуемо, дёшево, легко тестировать и проверять | Жёстко; ломается на непредвиденных путях | Шаги известны заранее |
| Автономный одиночный агент | Гибко; справляется с открытыми целями | Труднее контролировать, оценивать и ограничивать | Путь нельзя определить заранее |
| Оркестрация многих агентов | Параллелизм; специализированные роли | Цена координации, накапливающиеся ошибки, выше расходы | Задача действительно раскладывается на независимые части |
| Действие без присмотра | Быстро, малое трение | Ошибки исполняются без проверки | Действия обратимы и малоценны |
| Барьер человека в контуре | Безопасность, подотчётность, обратимость | Медленнее; нужна мощность рецензентов | Действия значимы или необратимы |
Центральное напряжение это автономия против контроля. Больше автономии справляется с большим числом ситуаций, но требует больше ограничителей, больше оценки и больше денег и отказывает способами, труднее предсказуемыми. Проекты со многими агентами соблазняют команды элегантностью, однако каждый дополнительный агент добавляет накладные расходы координации и ещё одно место, где малая ошибка накапливается в неверный результат. Разрешайте напряжение, начиная с наименьшей автономии, решающей проблему, и добавляя свободу, только когда этого требует конкретная задача, всегда в паре с соответствующим ограничителем.
Вопросы для обсуждения с командой
Действительно ли этой функции нужен агент или фиксированный рабочий процесс был бы безопаснее и дешевле? Автономия соблазнительна, но у большинства задач есть узнаваемые шаги, которые оркестрируемый конвейер обрабатывает с гораздо меньшим риском. Для большой команды умолчание в пользу агентов означает, что каждая группа берёт на себя бремя оценки, трассировки и безопасности, которого избежал бы более простой проект. Принесите конкретную задачу и спросите, можно ли определить её шаги заранее; если можно, агент, вероятно, излишнее усложнение. Оставляйте неограниченную автономию для целей, где путь действительно варьируется от случая к случаю. Ответ должен подтолкнуть большинство функций к рабочему процессу и оставить небольшой намеренный набор настоящими агентами.
Для каждого инструмента, который может вызвать наш агент, какое худшее может сделать с ним захваченный агент и что это останавливает? Внедрение через промпт и атаки запутавшегося заместителя обращают собственный законный доступ агента против вас, поэтому правильная линза состязательная (глава 4.2). Составьте опись каждого инструмента, области его привилегий и того, может ли вредоносная инструкция, протащенная через принимаемое содержимое, до него дотянуться. Для корпораций, подключающих агентов к внутренним системам, именно здесь наименьшие привилегии, песочница и человеческие барьеры на необратимые действия становятся реальными. Принесите список инструментов и учётные данные, которые держит каждый. Если какое-либо значимое действие достижимо без проверки или человеческого контроля, это первое, что нужно исправить.
Как мы узнаем, что доля успеха агента упала, учитывая, что каждый запуск выглядит правдоподобно? Агенты недетерминированы, поэтому запись, хорошо читающаяся, всё равно могла совершить неверное действие, а один зелёный запуск ничего не доказывает. Спросите, есть ли у вас набор оценки целей с проверяемыми исходами, запускаемый много раз на случай для получения доли успеха, а не единственного прохода. Для развёртываний высоких ставок или публичных обсудите, как трассировки запусков позволяют реконструировать, что именно произошло, когда что-то пошло не так (главы 6.5 и 6.6). Если ваш единственный сигнал жалобы пользователей, вы уже опоздали. Ответ должен финансировать стенд оценки до масштаба, а не после инцидента.
Какие действия этого агента по-настоящему необратимы, у кого полномочия их утверждать и есть ли у нас мощность рецензентов для укомплектования этого барьера? Соблазн позволить модели действовать без присмотра везде, но человеческий барьер реален, только если названный человек с полномочием сказать «нет» доступен, когда агент спрашивает. Для большой команды очередь утверждения, которой никто не владеет, тихо становится печатью «не глядя», а спроектированная вами безопасность испаряется под объёмом. Принесите полный список действий, которые агент может совершить, пометьте каждое обратимым или необратимым и оцените суточный объём случаев с низкой уверенностью, которые ляжут на рецензента. Взвесьте трение и цену комплектования барьера против радиуса поражения ошибки без присмотра и предпочитайте переделку необратимого действия в поэтапное отменяемое добавлению ещё одного рецензента. В корпоративной и государственной среде привязывайте каждое значимое действие к подотчётному должностному лицу и записи управления изменениями, потому что автономное действие, затрагивающее гражданина или клиента, которое никто из людей не утвердил, именно тот отказ, что найдёт аудит.
Тянемся ли мы к проекту со многими агентами потому, что задача действительно раскладывается, или потому, что он выглядит элегантно? Разделение работы между специализированными агентами соблазнительно, однако каждый лишний агент добавляет накладные расходы координации и ещё одно место, где малая ошибка накапливается в неверный результат. Для большой организации цена не только расходы и задержка: систему со многими агентами гораздо труднее трассировать, оценивать и осмыслять при отказе, так что бремя управления умножается с каждой добавленной ролью. Принесите задачу и покажите конкретно, какие части работают независимо и параллельно, затем сравните измеренные долю успеха и стоимость версии со многими агентами с одиночным агентом на том же наборе оценки. Если одиночный агент побеждает или равен, элегантный проект излишнее усложнение. Для регулируемых или публичных развёртываний помните, что каждый агент в цепочке ещё один компонент, который орган надзора должен иметь возможность проверить, поэтому добавленная структура, которую вы не можете обосновать, добавленное обязательство.
Каковы жёсткие бюджеты на шаги, время и расходы агента и как зацикливающийся агент был бы пойман до того, как набьёт цену или задержку? Агент, повторяющий проваливающееся действие, может сжечь деньги и время без предупреждения, поэтому неограниченная автономия финансовый риск не меньше риска безопасности. Для большой команды, ведущей много агентов, один плохо ведущий себя цикл может вызвать скачок облачного счёта или исчерпать лимит скорости, лишающий все остальные нагрузки, что делает потолки на запуск общей эксплуатационной заботой, а не проблемой одной команды. Принесите текущие бюджеты шагов, времени и токенов для каждого агента, оповещение, срабатывающее при их превышении запуском, и обнаружение циклов, отказывающее безопасно, а не барахтающееся. Взвесьте тугие бюджеты, которые могут обрезать законно трудную задачу, против свободных, позволяющих стоимости убежать. В корпоративной и государственной среде, где расходы нужно прогнозировать и обосновывать, агент с неограниченной стоимостью статья, которую нельзя защитить на бюджетной рецензии или при аудите.
Взгляд по секторам
Стартап. Выпустите одного узкого агента, касающегося вашей основной ценности, на размещённой модели, с наименьшим набором инструментов, который справляется с работой, и жёстким потолком на шаги и расходы. Сопротивляйтесь демонстрации многих агентов: ваше дефицитное инженерное внимание лучше потратить на ограничение автономии одиночного агента и трассировку его запусков, чем на координацию ролей, которые вы не сможете сопровождать. Держите каждое значимое действие за единым барьером «черновик, никогда не отправлять», чтобы ошибка стоила одного щелчка отмены, а не инцидента.
Малый бизнес. Некому вести стенд оценки или песочницу, поэтому предпочитайте агентов, встроенных в уже доверенные инструменты, и включайте только ту автономию, которую можете контролировать на глаз. Воспринимайте любого агента, способного отправлять, платить или удалять от вашего имени, как то, что нужно держать выключенным, пока человек не подтвердит каждое действие, потому что неверное автоматическое сообщение клиенту стоит вам отношений. Отдавайте предпочтение поставщикам, показывающим, что сделал агент, и позволяющим выключить автоматизацию.
Крупная организация. Проблема управление агентами по многим командам: общие шаблоны ограничения автономии, учётные данные инструментов с наименьшими привилегиями, песочница, барьеры человека в контуре и сквозная трассировка, чтобы ни одна группа не изобретала ограничители заново. Подключайте агентов к внутренним системам под теми же средствами контроля доступа, какие держал бы человек, закрывайте необратимые действия за названными утверждающими и управлением изменениями и управляйте портфелем метриками доли успеха, бюджетами на запуск и состязательным тестированием внедрения. Стандартизируйте слой трассировки и оценки, чтобы поведение любого агента можно было реконструировать и проверить.
Государственный сектор. Закупки, прозрачность и публичная подотчётность ограничивают каждый выбор. Держите агентов сбором фактов и составлением черновиков и оставляйте каждое решение, затрагивающее гражданина, подотчётному человеку, потому что ответственность за решение государственного сектора нельзя делегировать модели. Журналируйте каждый запуск, чтобы орган надзора мог увидеть, какие источники привлекались и что было сделано, требуйте от поставщиков раскрытия инструментов и ограничений агента и докажите состязательным набором оценки, что агент отказывается действовать за пределами своего ограниченного круга.
Примеры
Стартап. Аналитический стартап из пяти человек строит агента сортировки поддержки. Он читает входящую заявку, ищет в документации и либо составляет ответ, либо направляет заявку человеку, и это весь набор инструментов. Учётные данные только для чтения плюс единственное действие «создать черновик», никогда не отправляющее без щелчка человека. Каждый запуск трассируется, чтобы основатели видели, почему заявка направлена туда, куда направлена, а ночной набор оценки из пятидесяти реальных заявок запускает агента по пять раз на каждую для отслеживания точности маршрутизации. Когда хитроумная демонстрация конкурента со многими агентами их соблазняет, они остаются на одиночном агенте, потому что их задача не раскладывается.
Крупная организация. Банк строит агента, помогающего операционному персоналу сверять неудавшиеся платежи. Он интегрируется с внутренними системами под теми же средствами контроля доступа, что у сотрудника-человека, через учётные данные сервиса с наименьшими привилегиями, ограниченные только сверкой. Агент может свободно исследовать (читать журналы учёта, искать историю транзакций), но любое действие, перемещающее деньги или правящее запись, ставится в очередь и требует названного человека-утверждающего, удовлетворяя управлению изменениями. Принимаемые документы воспринимаются как недоверенные для притупления внедрения через промпт, инструменты работают в песочнице, а каждый запуск трассируется от конца до конца для аудита. Офлайн-набор оценки управляет каждым изменением модели или промпта, а бюджеты на запуск ограничивают шаги и расходы, так что зацикливающийся агент не может набить цену или задержку.
Государственный сектор. Ведомство пособий пилотирует агента, помогающего социальным работникам собирать факты по заявке: извлекать записи, проверять правила права и составлять резюме. Ведомство проводит жёсткую линию: агент собирает и составляет черновик, а социальный работник принимает и отвечает за каждое решение, затрагивающее гражданина, потому что подотчётность за решения государственного сектора нельзя делегировать модели (глава 6.5). Каждый запуск полностью журналируется, показывая, какие источники привлекались и что было составлено, так что орган надзора может проверить любое дело. Автономия намеренно ограничена чтением и составлением черновика, инструменты с наименьшими привилегиями и в песочнице, а состязательный набор оценки подтверждает, что агент отказывается действовать за пределами сбора фактов.
Бизнес-обоснование: мотивы, ROI и TCO
Агенты дают отдачу автоматизацией многошаговой работы, раньше требовавшей человека, щёлкающего между системами: сортировка, сверка, исследование и рутинные операции. Ценность проявляется как работа, завершённая без человека на каждом шаге, более быстрые циклы и персонал, освобождённый для задач, требующих суждения. Поскольку агенты строятся на существующих LLM и инструментах, время до работающего прототипа коротко, именно поэтому команды переусложняют.
Совокупная стоимость владения то, чем агенты отличаются от простых функций на LLM. Сверх цены вывода вы платите за интеграции инструментов, песочницу и сантехнику разрешений, стенд оценки, стек трассировки и наблюдаемости (глава 6.6) и человеческих рецензентов, комплектующих барьеры утверждения. Зацикливающийся или плохо ограниченный агент добавляет переменную цену, способную подскочить без предупреждения, поэтому бюджеты на шаги и расходы часть проекта, а не запоздалая мысль. Цена непринятия более медленные операции и ручная рутина, которую конкуренты автоматизируют. Цена небрежного принятия автономное действие, отправляющее неверное сообщение, допускающее утечку данных или принимающее неподотчётное решение. Обосновывайте перед руководством, сочетая одну конкретную цель автоматизации с конкретным планом ограничителей, оценки и человеческого надзора и честно признавая, что ограничители это большая часть стоимости.
Антипаттерны и ловушки
- Агент там, где хватило бы рабочего процесса. Принятие полного риска автономии для задачи, чьи шаги были известны.
- Слишком широкие инструменты и учётные данные. Один инструмент «сделай что угодно» вместо узких с наименьшими привилегиями.
- Слепота к внедрению через промпт. Подача недоверенного содержимого агенту, держащему реальные привилегии.
- Нет человеческого барьера на необратимые действия. Позволение модели отправлять, платить или удалять без проверки.
- Театр многих агентов. Разделение простой задачи между агентами, оплата цены координации без выигрыша.
- Оценка на ощущениях. Суд по тому, как читается запись, вместо доли успеха задачи.
- Неограниченные циклы. Нет потолка на шаги, время или расходы, так что застрявший агент сжигает деньги и задержку.
- Нетрассируемые запуски. Нет записи того, что сделал агент, из-за чего нельзя отладить, проверить или ответить.
Модель зрелости
- Уровень 1, Начальный: Агенты прототипируются стихийно с широким доступом к инструментам и без границ. Успех оценивается по демонстрациям, реактивно, после того как что-то сломалось. Нет ни набора оценки, ни трассировки, ни человеческого барьера на значимые действия.
- Уровень 2, Развитие: У некоторых агентов есть ограниченные циклы и инструменты с наименьшими привилегиями, и существует базовая трассировка, но практика различается по командам. Ручной набор оценки ловит грубые регрессии в нескольких проектах, а в других его нет. Человеческое утверждение охраняет самые очевидные необратимые действия, но покрытие неравномерно и недокументировано.
- Уровень 3, Стандартизация: Общие шаблоны управляют автономией, разрешениями инструментов, песочницей и барьерами человека в контуре, документированные и принуждаемые по каждой команде. Каждое значимое действие закрыто барьером или проверено, агенты трассируются от конца до конца, а автоматический набор оценки с оценкой долей успеха запускается на каждое изменение. Внедрение через промпт воспринимается как постоянная угроза с определённым откликом.
- Уровень 4, Управление: Портфель агентов измеряется и контролируется относительно базовых значений. Доля успеха на задачу, доля прохождения защиты от внедрения через промпт, цена и число шагов на запуск, задержка человеческого утверждения и инциденты циклов или отказов отслеживаются как метрики; пороги отката и убийства принуждаются по этим свидетельствам, а не жалобам. Бюджеты на запуск по шагам, времени и расходам мониторятся, а регрессия любой метрики запускает действие до масштаба, а не после инцидента.
- Уровень 5, Оркестрация: Автономия подбирается под риск задачи политикой и подстраивается непрерывно по мере поступления результатов. Постоянная офлайн- и онлайн-оценка привязывает поведение агента к бизнес-результатам, а организация регулярно выводит, пересматривает или заново наделяет разрешениями агентов по мере сдвигов картины рисков. Трассировка, бюджеты стоимости и следы аудита единообразны по портфелю; защиты от внедрения и запутавшегося заместителя тестируются состязательно; подотчётность за автономные действия ясна и проверяема.
Идеи для обсуждения
- Какие из ваших нынешних функций на LLM тихо стали агентами и ограничена ли автономия каждой намеренно?
- Каков для каждого инструмента агента дешевейший способ, которым атакующий мог бы им злоупотребить через внедрённое содержимое, и что это останавливает?
- Где вы выбрали проекты со многими агентами и можете ли показать, что цена координации окупилась против одиночного агента?
- Какие действия агента по-настоящему необратимы и мог ли бы каждое быть переделано в обратимое или поэтапное?
- Если бы агент завтра совершил вредное действие, могли бы вы реконструировать, что именно он сделал и кто был подотчётен?
Главные выводы
- Агент это LLM в цикле с инструментами, памятью и целью. Риск живёт в цикле и инструментах, а не тексте.
- Предпочитайте фиксированный рабочий процесс, когда шаги известны; оставляйте автономию для действительно открытых целей и ограничивайте её туго.
- Использование инструментов основная возможность. Давайте каждому инструменту наименьшие привилегии, проверяемую схему и песочницу.
- Закрывайте значимые и необратимые действия за человеком с реальными полномочиями и проектируйте дешёвую отмену.
- Воспринимайте агентов как состязательную среду: защищайтесь от внедрения через промпт и злоупотребления запутавшегося заместителя (глава 4.2).
- Оценивайте по доле успеха задачи по многим запускам и трассируйте каждый запуск для отладки, контроля стоимости и аудита (главы 6.5 и 6.6).
- Нередко правильный ответ вообще не строить агента.
Источники и дополнительное чтение
- Shunyu Yao et al., ReAct: Synergising Reasoning and Acting in Language Models.
- Timo Schick et al., Toolformer: Language Models Can Teach Themselves to Use Tools.
- Anthropic, Building Effective Agents (engineering guidance on workflows versus agents).
- OWASP Foundation, OWASP Top 10 for Large Language Model Applications (including prompt injection and excessive agency).
- Simon Willison, writing on prompt injection and the “lethal trifecta” for AI agents.
- Norman Hardy, The Confused Deputy (the classic statement of the confused-deputy problem).
- Chip Huyen, AI Engineering: Building Applications with Foundation Models.
- Stuart Russell and Peter Norvig, Artificial Intelligence: A Modern Approach (intelligent agents and rational action).