بناء خط أنابيب لأتمتة تطبيقات متعددة
ربط Gmail ← Slack ← Google Sheets عبر استدعاءات الأدوات التي يديرها الوكيل.
بناء خط أنابيب لأتمتة تطبيقات متعددة درس مجاني في AI Agents على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Agents، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Agents 4 دروس في المجموع.
خط أنابيب التطبيقات المتعددة
يربط خط أنابيب التطبيقات المتعددة عدة خدمات في سير عمل آلي واحد. في هذا الدرس سنبني: بريد إلكتروني جديد في Gmail ← يقرأ الوكيل البريد ويستخرج بنود العمل ← ينشئ بطاقة في Trello ← يرسل إشعارًا إلى Slack.
بنية خط الأنابيب
يتكوّن خط الأنابيب من أربع مراحل:
- التشغيل: يكتشف إشعار الدفع من Gmail أو الاستطلاع بريدًا إلكترونيًا جديدًا
- الاستخراج: يقرأ LLM البريد الإلكتروني ويستخرج بنود العمل
- الإنشاء: تنشئ Trello API بطاقةً لكل بند عمل
- الإشعار: تنشر Slack API رسالةً تلخيصية
كل مرحلة دالة مستقلة ذات مدخلات ومخرجات واضحة.
from dataclasses import dataclass, field
from typing import List
@dataclass
class Email:
id: str
sender: str
subject: str
body: str
@dataclass
class ActionItem:
title: str
description: str
due_date: str = None
@dataclass
class PipelineResult:
email_id: str
action_items: List[ActionItem] = field(default_factory=list)
trello_card_ids: List[str] = field(default_factory=list)
slack_message_ts: str = None
error: str = None
if __name__ == '__main__':
email = Email(id='e1', sender='alice@example.com', subject='Project update', body='See attached.')
result = PipelineResult(email_id=email.id, action_items=[ActionItem(title='Review attachment', description='Check the doc')])
print(f'Pipeline result for {result.email_id}: {len(result.action_items)} action item(s)')
print(' -', result.action_items[0].title)
المرحلة 1: قراءة رسائل البريد الإلكتروني
استخدم Gmail API لجلب رسائل البريد الإلكتروني الجديدة. تتولى مكتبة google-api-python-client المصادقة واستدعاءات API. نستطلع الرسائل التي لم تُشاهد بعد.
from googleapiclient.discovery import build
from google.oauth2.credentials import Credentials
import base64
def get_gmail_service(token_path='token.json'):
creds = Credentials.from_authorized_user_file(token_path)
return build('gmail', 'v1', credentials=creds)
def fetch_unread_emails(service, max_results=10):
results = service.users().messages().list(
userId='me',
q='is:unread',
maxResults=max_results
).execute()
messages = results.get('messages', [])
emails = []
for msg in messages:
detail = service.users().messages().get(
userId='me', id=msg['id'], format='full'
).execute()
headers = {h['name']: h['value'] for h in detail['payload']['headers']}
emails.append(Email(
id=msg['id'],
sender=headers.get('From', ''),
subject=headers.get('Subject', ''),
body=extract_body(detail)
))
return emails
def extract_body(message_detail):
payload = message_detail.get('payload', {})
if 'data' in payload.get('body', {}):
return base64.urlsafe_b64decode(payload['body']['data']).decode('utf-8')
return ''المرحلة 2: استخراج بنود العمل
مرّر محتوى البريد الإلكتروني إلى LLM واطلب منه استخراج بنود العمل بتنسيق JSON منظّم. استخدم response_format للحصول على مخرجات JSON موثوقة.
import openai
import json
client = openai.OpenAI(api_key='sk-...')
def extract_action_items(email: 'Email') -> list:
prompt = (
'Extract all action items from this email. '
'Return JSON array with objects having fields: '
'title (string), description (string), due_date (string or null).\n\n'
f'From: {email.sender}\n'
f'Subject: {email.subject}\n'
f'Body:\n{email.body}'
)
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}],
response_format={'type': 'json_object'}
)
result = json.loads(response.choices[0].message.content)
items = result.get('action_items', [])
return [
ActionItem(
title=item['title'],
description=item.get('description', ''),
due_date=item.get('due_date')
)
for item in items
]المرحلة 3: إنشاء بطاقات Trello
تنشئ Trello REST API بطاقات باستخدام طلب POST بسيط. ستحتاج إلى مفتاح API والرمز المميز ومعرّف القائمة التي ينبغي إنشاء البطاقات فيها.
import httpx
TRELLO_API_KEY = 'your-trello-api-key'
TRELLO_TOKEN = 'your-trello-token'
TRELLO_LIST_ID = 'your-list-id'
def create_trello_card(action_item: 'ActionItem') -> str:
url = 'https://api.trello.com/1/cards'
params = {
'key': TRELLO_API_KEY,
'token': TRELLO_TOKEN
}
data = {
'name': action_item.title,
'desc': action_item.description,
'idList': TRELLO_LIST_ID,
'due': action_item.due_date
}
response = httpx.post(url, params=params, json=data)
response.raise_for_status()
card = response.json()
return card['id']
def create_trello_cards_for_items(action_items: list) -> list:
card_ids = []
for item in action_items:
card_id = create_trello_card(item)
print(f'Created Trello card: {item.title} (ID: {card_id})')
card_ids.append(card_id)
return card_idsالمرحلة 4: إرسال إشعار Slack
استخدم Slack SDK لإرسال رسالة تلخيصية منسّقة إلى قناة. ينبغي أن تلخّص الرسالة بوضوح بنود العمل التي استُخرجت وأُنشئت.
from slack_sdk import WebClient
slack_client = WebClient(token='xoxb-your-slack-bot-token')
def send_slack_summary(email: 'Email', action_items: list, card_ids: list, channel: str = '#automation'):
if not action_items:
return None
items_text = '\n'.join([
f' - {item.title}'
for item in action_items
])
message = (
f'*New email processed from {email.sender}*\n'
f'*Subject:* {email.subject}\n\n'
f'*Action items extracted ({len(action_items)}):*\n'
f'{items_text}\n\n'
f'Trello cards created: {len(card_ids)}'
)
response = slack_client.chat_postMessage(
channel=channel,
text=message,
mrkdwn=True
)
return response['ts']معالجة الأخطاء في كل مرحلة
لا يكون خط الأنابيب متينًا إلا بقدر متانة معالجة أخطائه. يمكن أن تفشل كل مرحلة بشكل مستقل. غلّف كل استدعاء، وسجّل الخطأ، وحدد ما إذا كان ينبغي متابعة خط الأنابيب أو إيقافه.
import logging
logger = logging.getLogger('pipeline')
def run_pipeline_stage(stage_name, fn, *args, **kwargs):
try:
result = fn(*args, **kwargs)
logger.info(f'Stage {stage_name}: success')
return result, None
except Exception as e:
logger.error(f'Stage {stage_name}: FAILED - {e}')
return None, str(e)
def process_email_pipeline(email):
# Stage 2: Extract
action_items, err = run_pipeline_stage('extract', extract_action_items, email)
if err:
return PipelineResult(email_id=email.id, error=f'Extract failed: {err}')
if not action_items:
logger.info(f'No action items found in email {email.id}')
return PipelineResult(email_id=email.id, action_items=[])
# Stage 3: Trello
card_ids, err = run_pipeline_stage('trello', create_trello_cards_for_items, action_items)
if err:
card_ids = [] # Continue even if Trello fails
# Stage 4: Slack
ts, err = run_pipeline_stage('slack', send_slack_summary, email, action_items, card_ids or [])
return PipelineResult(
email_id=email.id,
action_items=action_items,
trello_card_ids=card_ids or [],
slack_message_ts=ts
)التسجيل المنظّم لخطوط الأنابيب
استخدم التسجيل المنظّم حتى تتمكن من الاستعلام عن سجل تنفيذ خط الأنابيب. سجّل بدء خط الأنابيب واكتمال كل مرحلة والنتيجة النهائية ككائنات JSON.
import logging
import json
from datetime import datetime
class PipelineLogger:
def __init__(self, pipeline_name):
self.pipeline_name = pipeline_name
self.logger = logging.getLogger(pipeline_name)
self.run_id = None
self.start_time = None
def start(self, email_id):
self.run_id = f'{email_id}_{int(datetime.now().timestamp())}'
self.start_time = datetime.now()
self.logger.info(json.dumps({
'event': 'pipeline_start',
'run_id': self.run_id,
'email_id': email_id
}))
def stage_done(self, stage, result_summary):
self.logger.info(json.dumps({
'event': 'stage_complete',
'run_id': self.run_id,
'stage': stage,
'result': result_summary
}))
def finish(self, success, details):
duration = (datetime.now() - self.start_time).total_seconds()
self.logger.info(json.dumps({
'event': 'pipeline_finish',
'run_id': self.run_id,
'success': success,
'duration_seconds': duration,
'details': details
}))
if __name__ == '__main__':
import sys
logging.basicConfig(level=logging.INFO, format='%(message)s', stream=sys.stdout)
pl = PipelineLogger('demo_pipeline')
pl.start('email_123')
pl.stage_done('extract', {'items_found': 3})
pl.finish(True, {'action_items': 2})
المشغّل الرئيسي لخط الأنابيب
يربط المشغّل الرئيسي جميع المكوّنات معًا. فهو يتحقّق من وجود رسائل بريد إلكتروني جديدة، ويعالج كل رسالة عبر خط الأنابيب، ثم يضع علامة «مقروءة» عليها لتجنّب معالجتها مرة أخرى.
import time
def mark_as_read(gmail_service, email_id):
gmail_service.users().messages().modify(
userId='me',
id=email_id,
body={'removeLabelIds': ['UNREAD']}
).execute()
def run_email_pipeline_loop(gmail_service, poll_interval=60):
pipeline_logger = PipelineLogger('email_pipeline')
print(f'Pipeline running. Polling every {poll_interval}s')
while True:
try:
emails = fetch_unread_emails(gmail_service)
print(f'Found {len(emails)} unread emails')
for email in emails:
pipeline_logger.start(email.id)
result = process_email_pipeline(email)
if result.error:
pipeline_logger.finish(False, {'error': result.error})
else:
mark_as_read(gmail_service, email.id)
pipeline_logger.finish(True, {
'action_items': len(result.action_items),
'cards_created': len(result.trello_card_ids)
})
except Exception as e:
print(f'Pipeline loop error: {e}')
time.sleep(poll_interval)إدارة الإعدادات
احتفظ بجميع بيانات اعتماد API وإعدادات خط الأنابيب في متغيّرات البيئة، وليس في الشيفرة. وحمّلها عند بدء التشغيل، وتحقّق من وجود المفاتيح المطلوبة.
import os
from dotenv import load_dotenv
load_dotenv()
class PipelineConfig:
def __init__(self):
self.openai_api_key = os.environ.get('OPENAI_API_KEY', '')
self.slack_bot_token = os.environ.get('SLACK_BOT_TOKEN', '')
self.trello_api_key = os.environ.get('TRELLO_API_KEY', '')
self.trello_token = os.environ.get('TRELLO_TOKEN', '')
self.trello_list_id = os.environ.get('TRELLO_LIST_ID', '')
self.slack_channel = os.environ.get('SLACK_CHANNEL', '#automation')
self.poll_interval = int(os.environ.get('POLL_INTERVAL_SECONDS', '60'))
def validate(self):
missing = []
required = [
('OPENAI_API_KEY', self.openai_api_key),
('SLACK_BOT_TOKEN', self.slack_bot_token),
('TRELLO_API_KEY', self.trello_api_key),
('TRELLO_TOKEN', self.trello_token),
('TRELLO_LIST_ID', self.trello_list_id)
]
for name, value in required:
if not value:
missing.append(name)
if missing:
raise ValueError(f'Missing required config: {missing}')
return True
config = PipelineConfig()
config.validate()
print('Config validated successfully')اختبار خط الأنابيب
اختبر كل مرحلة من مراحل خط الأنابيب بشكل مستقل باستخدام بيانات وهمية قبل إجراء الاختبار الشامل من البداية إلى النهاية. يتيح لك ذلك التحقّق من المنطق دون استهلاك أرصدة API أو إنشاء بطاقات Trello فعلية.
from unittest.mock import MagicMock, patch
def test_extract_action_items_mock():
mock_response = MagicMock()
mock_response.choices[0].message.content = '{"action_items": [{"title": "Follow up with vendor", "description": "Call about invoice", "due_date": null}]}'
with patch('openai.OpenAI') as mock_openai:
mock_client = MagicMock()
mock_client.chat.completions.create.return_value = mock_response
mock_openai.return_value = mock_client
test_email = Email(
id='test123',
sender='vendor@example.com',
subject='Invoice Follow-up Needed',
body='Please follow up with the vendor about the outstanding invoice.'
)
# Would call extract_action_items(test_email) with mocked OpenAI
print('Test email:', test_email.subject)
print('Mock response parsed successfully')
test_extract_action_items_mock()اختبار المعرفة: خط أنابيب متعدد التطبيقات
اختبر مدى فهمك لبناء خطوط أنابيب للأتمتة متعددة التطبيقات.
مراجعة خط الأنابيب
لقد بنيت خط أنابيب متكاملًا للأتمتة متعددة التطبيقات: اكتشاف الرسائل في Gmail، والاستخراج المستند إلى LLM، وإنشاء بطاقات Trello، وإرسال إشعارات Slack. وتتمثل مبادئ التصميم الأساسية في فصل المراحل بواجهات واضحة، ومعالجة الأخطاء بفعالية في كل خطوة، وتسجيل الأحداث بطريقة منظمة، وإدارة الإعدادات عبر متغيّرات البيئة.
الأسئلة الشائعة
هل درس «بناء خط أنابيب لأتمتة تطبيقات متعددة» مجاني؟
نعم — نص درس «بناء خط أنابيب لأتمتة تطبيقات متعددة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Agents، انتقل إلى CoddyKit PRO. تتضمن دورة AI Agents 4 دروس في المجموع.
ماذا ستتعلم في «بناء خط أنابيب لأتمتة تطبيقات متعددة»؟
ربط Gmail ← Slack ← Google Sheets عبر استدعاءات الأدوات التي يديرها الوكيل. تتمرن على AI Agents مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ AI Agents؟
لا تُشترط خبرة سابقة. AI Agents على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «بناء خط أنابيب لأتمتة تطبيقات متعددة»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس AI Agents هذا؟
نعم. كل درس في AI Agents يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أنماط وكلاء المحفز والإجراء
- ربط الوكلاء بـ Webhooks
- الوكلاء المجدولون والقائمون على Cron
- بناء خط أنابيب لأتمتة تطبيقات متعددة