Effective context engineering for AI agents
Контекст — это конечный ресурс для ИИ-агентов, требующий стратегического управления. В отличие от традиционного промт-инжиниринга, который фокусируется на формулировке инструкций, контекст-инжиниринг охватывает всё содержимое контекстного окна: системные промты, историю сообщений, данные инструментов и внешнюю информацию. Это особенно критично для агентов, работающих в циклах, где объём релевантных данных постоянно растёт, но эффективность модели снижается из-за «контекстного распада» — ухудшения точности recall при увеличении числа токенов.
Архитектурные ограничения трансформеров усугубляют проблему: внимание модели распределяется между всеми токенами, создавая квадратичный рост вычислительной нагрузки. Модели, обученные на коротких последовательностях, хуже справляются с длинным контекстом, даже с техниками вроде интерполяции позиционных энкодингов. Ключевой вывод: контекст нужно тщательно курировать, как稀缺ный ресурс, чтобы сохранять фокус и избегать перегрузки внимания ИИ.
Комментарии (24)
- Обсуждение ограничений и инженерных подходов к работе с малыми окнами контекста (4K у Apple) по сравнению с большими окнами других моделей.
- Критика отсутствия удобных инструментов для визуализации и управления контекстом, а также предложения по улучшению (DSPy, OpenTelemetry, структурированный вывод).
- Стратегии работы с ограниченным контекстом: уточнение задачи и файлов в первом сообщении, создание новых сессий, структурирование вывода через JSON schema.
- Дебаты о том, являются ли эффективные методы инженерного контекста коммерческой тайной, и скептицизм по этому поводу.
- Прогнозы, что удешевление и увеличение контекста LLM могут сделать проблему менее актуальной в долгосрочной перспективе.
LLM Observability in the Wild – Why OpenTelemetry Should Be the Standard
Разработчики сталкиваются с хаосом при отладке LLM-агентов в продакшене из-за фрагментации стандартов observability. Например, OpenAI предлагает детальные трейсы, но они привязаны к её фреймворку и не позволяют фильтровать отдельные спаны. New Relic поддерживает OpenTelemetry, но интерфейс громоздок для оперативного дебаггинга. Phoenix с OpenInference даёт богатые AI-специфичные спаны, но не полностью совместим с OpenTelemetry и не имеет SDK для Ruby, что критично для таких проектов, как Chatwoot.
Ключевая проблема — противостояние универсального OpenTelemetry (широкая поддержка языков, но базовые типы спанов) и специализированного OpenInference (богатые AI-типы, но слабая экосистема). OpenInference лишь поверхностно совместим с OpenTelemetry, приводя к «unknown» спанам при прямом использовании. Это вынуждает команды выбирать между созданием кастомных SDK, потерей контекста или сменой стека, замедляя разработку. OpenTelemetry остаётся прагматичным выбором из-за зрелости и кросс-языковой поддержки, но требует расширения семантики под AI-workflow.
Комментарии (34)
- Разработка систем наблюдения (observability) для многозадачных LLM-агентов, включая метрики сложности задач и успешности выполнения.
- Обсуждение стандартов и инструментов (OpenTelemetry, Phoenix, Clickhouse) для отслеживания семантических ошибок и трассировки выполнения агентов.
- Критика подхода к оценке через ИИ из-за проблемы "курицы и яйца" и предложения использовать стандартные системы мониторинга.
- Вопросы о практическом применении длинных промптов не-техническими пользователями и динамической маршрутизации в агентах.
- Дискуссия о необходимости совмещения стандартных решений (реляционные БД) с OpenTelemetry для богатой семантики в распределённых системах.
OpenTelemetry collector: What it is, when you need it, and when you don't
OpenTelemetry Collector: что это, когда нужен и когда нет
Практическое руководство по OpenTelemetry Collector: что делает, как работает, архитектурные паттерны и как решить, нужен ли он вам для производительности, контроля, безопасности и экономии.
Нужен ли вам OpenTelemetry Collector? Для небольших проектов — возможно нет. Для production-среды с множеством сервисов, где важны стоимость, производительность и безопасность — почти наверняка да.
Краткое определение
OpenTelemetry Collector — это нейтральный к вендорам, расширяемый конвейер телеметрии, который принимает, обрабатывает и экспортирует данные (трейсы, метрики, логи) из ваших приложений в одно или несколько хранилищ.
Он позволяет:
- Очищать данные (удалять чувствительные поля, добавлять контекст)
- Пакетировать отправки и повторять при сбоях
- Применять умное семплирование (сохранять ошибки и редкие медленные трейсы)
- Сглаживать различия между версиями SDK
- Маршрутизировать данные в разные хранилища
- Служить защитным барьером между приложениями и интернетом
- Снижать затраты, отсеивая малополезную телеметрию
Архитектура
Без Collector (прямой экспорт)
Каждый сервис отправляет телеметрию напрямую в бэкенд:
Плюсы:
- Проще (меньше компонентов)
- Меньше операционных затрат
- Подходит для маленьких приложений / POC
Минусы:
- Каждый сервис сам handles retries, auth, backpressure
- Сложно менять экспортеры
- Нет централизованного семплирования / очистки / маршрутизации
- Риск misconfigurations
- Выше стоимость исходящего трафика при отправке в несколько систем
С центральным Collector
Все приложения отправляют данные в центральный Collector, который затем экспортирует:
Плюсы:
- Централизованная конфигурация: семплирование, очистка, обогащение
- Один канал исходящего трафика с пакетированием и retry
- Развязывает жизненный цикл приложения от изменений вендоров
- Меньше нагрузки на приложения
- Безопасность: приложения не выходят в интернет напрямую
Комментарии (27)
- Рекомендуется использовать коллектор OpenTelemetry для упрощения архитектуры, локальной отладки и управления аутентификацией
- Предлагается декаплеить коллектор от потребителей трассировок через брокеры сообщений (Kafka/NATS) для надежности и масштабируемости
- Коллектор рассматривается как защитный шлюз (read-only) между приложениями и базой данных для безопасности
- Отмечается сложность освоения OpenTelemetry, но подчеркивается его ценность как стандарта для интероперабельности
- Указывается полезность OTEL даже для монолитов благодаря возможностям корреляции и вложенных спэнов
- Обсуждаются альтернативы (Vector vs OTEL) и необходимость улучшения документации и примеров
- Упоминается использование коллектора для валидации и тестирования с помощью AI-агентов
What Are Traces and Spans in OpenTelemetry?
Trace — полный путь одного запроса через все сервисы.
Span — отдельный шаг в этом пути (функция, SQL, HTTP-вызов).
Root span — первый span (обычно входящий HTTP-запрос).
Child span — вложенный шаг.
Context — передаёт trace_id и текущий span по асинхронным вызовам.
Sampler — решает, записывать ли трассировку.
Exporter — отправляет spans в OneUptime, Jaeger и т.д.
Структура span
- name — короткое имя операции
- start/end time — длительность
- status — OK / ERROR
- attributes — произвольные метки (user_id, db.table)
- events — точки во времени (exception, cache hit)
- links — связи с другими traces
Быстрый старт в Node.js / TypeScript
npm i @opentelemetry/api @opentelemetry/sdk-node \
@opentelemetry/auto-instrumentations-node
// tracing.ts
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
const sdk = new NodeSDK({
serviceName: 'my-api',
traceExporter: new OTLPTraceExporter({ url: 'https://otlp.oneuptime.com' }),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
Ручная инструментация
import { trace } from '@opentelemetry/api';
const tracer = trace.getTracer('my-service');
async function getUser(id: string) {
return tracer.startActiveSpan('db.users.findById', async (span) => {
span.setAttributes({ 'db.table': 'users', 'user.id': id });
try {
const user = await db.users.findById(id);
span.setStatus({ code: SpanStatusCode.OK });
return user;
} catch (e) {
span.recordException(e);
span.setStatus({ code: SpanStatusCode.ERROR, message: e.message });
throw e;
} finally {
span.end();
}
});
}
Express/Fastify middleware
import { trace } from '@opentelemetry/api';
export function traceMiddleware(req, res, next) {
const span = trace.getTracer('http').startSpan(`${req.method} ${req.route?.path || req.url}`);
trace.getActiveContext().with(trace.setSpan(trace.getActiveContext(), span), () => {
res.on('finish', () => {
span.setAttributes({
'http.status_code': res.statusCode,
'http.method': req.method,
'http.route': req.route?.path,
});
span.end();
});
next();
});
}
Практические советы
- Именование:
verb noun(GET /users,db.users.insert). - Атрибуты: добавляйте
user.id,order.id,region. - Ошибки:
span.recordException(err)+span.setStatus({code: ERROR}). - Sampling: head-based (решение на старте) или tail-based (после завершения).
- Антипаттерны: слишком мелкие spans, отсутствие
span.end(), захардкоженные ID.
Сборка всего вместе
- Запустите SDK на старте приложения.
- Добавьте auto-instrumentations (http, express, pg, redis).
- Дополните ручными spans для критичных операций.
- Отправляйте traces в OneUptime → исследуйте flame-графы, ищите узкие места.
Комментарии (28)
- OTEL хвалят как стандарт, но реальные реализации сильно разнятся между вендорами и часто усложняют жизнь.
- Базовые понятия: span — это интервал работы с уникальным ID и ссылкой на родителя, trace — DAG спанов, рассказывающий историю запроса.
- Авто-инструментация почти даром даёт данные для JVM-приложений, но вне веб-бэкендов примеров мало и приходится искать «правильный» подмножество.
- Некоторые жалуются на объём кода и хранилище (десятки ТБ трейсов за неделю), другие считают это разовой настройкой и платой за прозрачность системы.
- Появляются упрощающие обёртки (Logfire, otelize) и примеры интеграции, но документация по дашбордам Grafana всё ещё вызывает трудности.