Kod
İş akışınızın içinden doğrudan JavaScript veya Python kodu yazın.
Genel bakış
Kod düğümünü, iş akışı verisini özel JavaScript veya Python koduyla doğrudan işlemek için kullanın. Standart düğümler yeterli olmadığında seçin; örneğin hesaplamalar, biçimlendirme, doğrulama, dosya işleme veya özel iş mantığı için.
Kod düğümünü ne zaman kullanmalı?
Kod düğümleri şunlar için idealdir:
- Veri dönüşümleri ve biçimlendirme
- Matematiksel hesaplamalar
- Özel iş mantığı
- JSON ayrıştırma ve manipülasyon
- Veri doğrulama ve temizleme
- Tarih/saat işlemleri
- JavaScript ve Python ile dosya işleme
Kod düğümlerinin ideal olmadığı durumlar:
- Yapay zeka analizi (Ajan düğümü kullanın)
- Harici API çağrıları (HTTP isteği düğümü kullanın)
- Basit koşullar (Koşul düğümü kullanın)
- Uzun süren veya etkileşimli analiz (Veri Analizi kullanın)
Yapılandırma
Dil: Kodunuzu JavaScript mi yoksa Python mı yazacağınızı seçin.
Kod düzenleyici: Kod düğümünü seçtiğinizde açılan kod düzenleyicide seçilen dilde dönüşüm mantığınızı yazın.
Önceki düğümlere erişim: Önceki düğümlerin çıktıları Kod düğümünde değişken olarak kullanılabilir. Kullanılabilir değişken adları kod düzenleyicinin üstünde gösterilir. Yalnızca slug’ları kodunuzda geçen yukarı akış düğümleri yüklenir. data’dan okumak veya çıktıları slug yerine dinamik aramak, her yukarı akış çıktısını yükler. Kod düğümü çıktısını daha sonra kullanmak için Kod çıktısına erişme sayfasına bakın.
Örnekler
İstatistik hesaplama
// Access data from previous nodes
const scores = agent.output.structured.scores || [];
// Calculate statistics
const average = scores.reduce((a, b) => a + b, 0) / scores.length;
const max = Math.max(...scores);
const min = Math.min(...scores);
// Return result
return {
average_score: average.toFixed(2),
highest_score: max,
lowest_score: min,
grade: average >= 90 ? "A" : average >= 80 ? "B" : "C"
}; # Access data from previous nodes
agent_output = agent.get("output", {})
scores = agent_output.get("structured", {}).get("scores", [])
if not scores:
return {
"average_score": 0,
"highest_score": None,
"lowest_score": None,
"grade": "N/A"
}
# Calculate statistics
average = sum(scores) / len(scores)
print(f"Processed {len(scores)} scores")
# Return result
return {
"average_score": round(average, 2),
"highest_score": max(scores),
"lowest_score": min(scores),
"grade": "A" if average >= 90 else "B" if average >= 80 else "C"
}Veriyi doğrulama ve temizleme
// Access form data
const email = trigger.output.email || "";
const amount = trigger.output.amount || 0;
// Validate
if (!email.includes("@")) {
throw new Error("Invalid email format");
}
if (amount <= 0) {
throw new Error("Amount must be greater than zero");
}
// Clean and return
return {
email: email.trim().toLowerCase(),
amount: parseFloat(amount.toFixed(2)),
validated: true
}; # Access form data
trigger_output = trigger.get("output", {})
email = trigger_output.get("email", "")
amount = trigger_output.get("amount", 0)
# Validate
if "@" not in email:
raise ValueError("Invalid email format")
if amount <= 0:
raise ValueError("Amount must be greater than zero")
# Clean and return
return {
"email": email.strip().lower(),
"amount": round(float(amount), 2),
"validated": True
}Dizileri dönüştürme ve filtreleme
// Access data from previous node
const customers = trigger.output.customers || [];
// Filter active customers
const activeCustomers = customers.filter(c => c.status === "active");
// Transform data
const processed = activeCustomers.map(customer => ({
id: customer.id,
name: `${customer.firstName} ${customer.lastName}`.trim(),
email: customer.email.toLowerCase(),
tier: customer.totalSpent > 1000 ? "premium" : "standard"
}));
return {
customers: processed,
total: processed.length,
premiumCount: processed.filter(c => c.tier === "premium").length
}; # Access data from previous node
customers = trigger.get("output", {}).get("customers", [])
# Filter active customers
active_customers = [
customer for customer in customers
if customer.get("status") == "active"
]
# Transform data
processed = [
{
"id": customer.get("id"),
"name": f"{customer.get('firstName', '')} {customer.get('lastName', '')}".strip(),
"email": customer.get("email", "").lower(),
"tier": "premium" if customer.get("totalSpent", 0) > 1000 else "standard"
}
for customer in active_customers
]
return {
"customers": processed,
"total": len(processed),
"premiumCount": len([c for c in processed if c["tier"] == "premium"])
}Tarih işlemleri
// Access event data
const events = trigger.output.events || [];
const now = new Date();
const processedEvents = events.map(event => {
const eventDate = new Date(event.date);
const daysUntil = Math.ceil((eventDate - now) / (1000 * 60 * 60 * 24));
return {
title: event.title,
date: eventDate.toISOString(),
formatted: eventDate.toLocaleDateString("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
}),
daysUntil: daysUntil,
isUpcoming: daysUntil >= 0,
isThisWeek: daysUntil >= 0 && daysUntil <= 7
};
});
return {
events: processedEvents,
upcomingCount: processedEvents.filter(e => e.isUpcoming).length,
thisWeekCount: processedEvents.filter(e => e.isThisWeek).length
}; from datetime import datetime, timezone
# Access event data
events = trigger.get("output", {}).get("events", [])
now = datetime.now(timezone.utc)
processed_events = []
for event in events:
event_date = datetime.fromisoformat(event["date"].replace("Z", "+00:00"))
days_until = (event_date.date() - now.date()).days
processed_events.append({
"title": event.get("title"),
"date": event_date.isoformat(),
"formatted": event_date.strftime("%A, %B %d, %Y"),
"daysUntil": days_until,
"isUpcoming": days_until >= 0,
"isThisWeek": 0 <= days_until <= 7
})
return {
"events": processed_events,
"upcomingCount": len([e for e in processed_events if e["isUpcoming"]]),
"thisWeekCount": len([e for e in processed_events if e["isThisWeek"]])
}JSON işleme
// Nested JSON from API response
const apiResponse = http_request.output || {};
// Extract and flatten nested data
const users = apiResponse.data?.users || [];
const flattened = users.map(user => ({
id: user.id,
name: `${user.first_name || ""} ${user.last_name || ""}`.trim(),
email: user.contact?.email || "",
city: user.address?.city || "Unknown",
isActive: user.status === "active"
}));
return {
users: flattened,
total: flattened.length,
activeCount: flattened.filter(u => u.isActive).length
}; # Nested JSON from API response
api_response = http_request.get("output", {})
# Extract and flatten nested data
users = api_response.get("data", {}).get("users", [])
flattened = [
{
"id": user.get("id"),
"name": f"{user.get('first_name', '')} {user.get('last_name', '')}".strip(),
"email": user.get("contact", {}).get("email", ""),
"city": user.get("address", {}).get("city", "Unknown"),
"isActive": user.get("status") == "active"
}
for user in users
]
return {
"users": flattened,
"total": len(flattened),
"activeCount": len([user for user in flattened if user["isActive"]])
}Birleştirme ve özetleme
// Sales data from previous node
const sales = http_request.output.sales || [];
// Group by category
const byCategory = {};
sales.forEach(sale => {
const cat = sale.category || "Other";
if (!byCategory[cat]) {
byCategory[cat] = { total: 0, count: 0, items: [] };
}
byCategory[cat].total += sale.amount || 0;
byCategory[cat].count += 1;
byCategory[cat].items.push(sale);
});
// Calculate summary
const summary = Object.entries(byCategory).map(([category, data]) => ({
category,
totalRevenue: data.total.toFixed(2),
orderCount: data.count,
averageOrder: (data.total / data.count).toFixed(2)
}));
// Sort by revenue
summary.sort((a, b) => parseFloat(b.totalRevenue) - parseFloat(a.totalRevenue));
return {
summary: summary,
topCategory: summary[0]?.category || "None",
grandTotal: sales.reduce((sum, s) => sum + (s.amount || 0), 0).toFixed(2)
}; # Sales data from previous node
sales = http_request.get("output", {}).get("sales", [])
# Group by category
by_category = {}
for sale in sales:
category = sale.get("category") or "Other"
if category not in by_category:
by_category[category] = {"total": 0, "count": 0, "items": []}
by_category[category]["total"] += sale.get("amount", 0)
by_category[category]["count"] += 1
by_category[category]["items"].append(sale)
# Calculate summary
summary = [
{
"category": category,
"totalRevenue": f"{data['total']:.2f}",
"orderCount": data["count"],
"averageOrder": f"{data['total'] / data['count']:.2f}"
}
for category, data in by_category.items()
]
# Sort by revenue
summary.sort(key=lambda row: float(row["totalRevenue"]), reverse=True)
return {
"summary": summary,
"topCategory": summary[0]["category"] if summary else "None",
"grandTotal": f"{sum(sale.get('amount', 0) for sale in sales):.2f}"
}JavaScript ile dosya oluşturma
JavaScript, bir files dizisi döndürerek iş akışı dosyaları üretebilir. Her giriş fileName, mimeType ve ya text (metin/CSV/JSON içerik) ya da base64 (ikili içerik) içermelidir. Çalışma zamanı dosyaları yükler ve düğüm çıktısına _files altında ekler.
const customers = trigger.output.customers || [];
const activeCustomers = customers.filter((c) => c.status === "active");
const csv = [
["id", "email"],
...activeCustomers.map((c) => [c.id, (c.email || "").toLowerCase()]),
]
.map((row) => row.map((cell) => `"${String(cell).replaceAll('"', '""')}"`).join(","))
.join("\n");
return {
active_count: activeCustomers.length,
files: [
{
fileName: "active_customers.csv",
mimeType: "text/csv",
text: csv,
},
],
};Önceki düğümlerden dosya okuma {#read-files-from-previous-nodes}
Form yüklemeleri veya aksiyon çıktıları gibi önceki düğümlerden geçen dosyalar Python çalışma dizininde kullanılabilir. Her dosya nesnesi doğrudan open()’a iletebileceğiniz bir path ve _metadata.name altında orijinal dosya adını taşır.
# File upload fields contain a list of file objects
files = trigger.get("output", {}).get("resume", [])
processed = []
for file in files:
with open(file["path"], "rb") as f:
content = f.read()
processed.append({
"name": file["_metadata"]["name"],
"size_bytes": len(content)
})
return {"files_processed": processed}Python ile dosya oluşturma
Python’un çalışma dizininde oluşturduğu dosyalar düğüm çıktısına _files altında eklenir.
import csv
customers = trigger.get("output", {}).get("customers", [])
active_customers = [c for c in customers if c.get("status") == "active"]
with open("active_customers.csv", "w", newline="") as file:
writer = csv.DictWriter(file, fieldnames=["id", "email"])
writer.writeheader()
for customer in active_customers:
writer.writerow({
"id": customer.get("id"),
"email": customer.get("email", "").lower()
})
print(f"Created CSV with {len(active_customers)} customers")
return {
"active_count": len(active_customers),
"file_name": "active_customers.csv"
}Kod çıktısına erişme {#accessing-code-output}
Sonraki düğümlerde JavaScript veya Python’dan dönen değerlere erişmek için Kod düğümü adını kullanın:
{{code_node_name.output.customer}}
{{code_node_name.output.total}}
{{code_node_name.output.formatted_date}}
{{code_node_name.output.processed_items[0].name}}JavaScript’in döndürdüğü veya Python’un çalışma dizininde oluşturduğu dosyalar _files altında kullanılabilir:
{{code_node_name.output._files[0]._metadata.name}}Dil yetenekleri
Kod düğümü yetenekleri seçilen dile bağlıdır.
JavaScript
JavaScript, yerleşik yardımcı işlevlerle güvenli bir sandbox ortamında çalışır:
ld.request(): HTTP istekleri yapınld.log(): Ayıklama bilgisi çıktılayın- Veri dönüşümleri: CSV, Parquet, Arrow biçim dönüşümleri
- Dosya oluşturma: Üretilen dosyaları
_filesaltında göstermek için birfilesdizisi döndürün - Standart JavaScript: JSON, Date, Math, Array, Object yöntemleri
- Tam yardımcılar referansı — Veri dönüşümleri, SQL doğrulama, kriptografi ve daha fazlası dahil tüm kullanılabilir sandbox yardımcılarını görüntüleyin.
Python
Python, internet erişimi olmayan bir sandbox ortamında çalışır.
- Düğüm çıktısını ayarlamak için üst düzey
returnkullanın - Günlük yazmak için
print()kullanın - pandas, numpy, openpyxl ve pypdf gibi önceden yüklü veri ve belge kitaplıklarını kullanın
- Slug’ları kodunuzda geçiyorsa ve geçerli Python tanımlayıcılarıysa yukarı akış çıktılarına değişken olarak erişin
file["path"]’iopen()’a ileterek önceki düğümlerden dosya okuyun_filesaltında göstermek için çalışma dizinine dosya kaydedin- İnternet erişimi olmadan çalışır
JavaScript ld.* yardımcıları Python’da kullanılamaz.
En iyi uygulamalar
Sonraki düğümlerde kolay erişim için veriyi nesne olarak döndürün. Bu, nokta notasyonuyla belirli değerlere başvurmayı basit kılar.
Veri tanımsız veya null olduğunda varsayılan değer sağlamak ve hataları önlemek için ||, isteğe bağlı zincirleme (?.) veya Python .get() kullanın.
Riskli işlemleri JavaScript için try/catch, Python için try/except ile sarın. Bu, iş akışı başarısızlıklarını önlemeye ve anlamlı hata mesajları sağlamaya yardımcı olur.
Karmaşık mantık bir Ajan düğümünde daha iyi olabilir. Kod düğümlerini basit dönüşümler ve hesaplamalar için kullanın; zekâ veya bağlam anlayışı gerektiren görevler için değil.
Kod düğümleri, yüklenen yukarı akış çıktıları 5 MiB’ı aştığında başarısız olur. Yalnızca ihtiyacınız olan slug’lara başvurun; çünkü data ve diğer dinamik çıktı aramaları her yukarı akış çıktısını yükler.
Kodunuzun ne yaptığını gelecekte başvurmak için belgeleyin. Net yorumlar, iş akışına daha sonra döndüğünüzde sizin ve ekibinizin mantığı anlamasına yardımcı olur.
Limitler {#limits}
Girdi boyutu
Her Kod düğümünün önceki düğümlerden aldığı birleşik girdi için 5 MiB limiti vardır. Kodunuz çalışmadan önce ajan, kodunuzun slug ile başvurduğu yukarı akış çıktılarının boyutunu ölçer. 5 MiB’ı aşarlarsa düğüm bir hatayla başarısız olur ve kodunuz hiç yürütülmez. data’dan okumak veya çıktıları slug yerine dinamik aramak her yukarı akış çıktısını yükler; bu nedenle tam birleşik boyut limite karşı ölçülür.
Yaygın nedenler:
- Birçok yinelemeden çıktıları tek bir diziye toplayan bir Döngü düğümü.
- Çok büyük bir API yanıtı, dosya içeriği veya veri kümesi döndüren önceki bir düğüm.
- Güvenle ölçülemeyen derin iç içe nesneler.
Bu limite takılırsanız şunlardan birini yapın:
- Yalnızca ihtiyacınız olan alanları filtreleyerek, özetleyerek veya seçerek yukarı akış düğüm çıktısının boyutunu azaltın.
- Önceki herhangi bir Döngü düğümünde yineleme başına daha az öğe işleyin.
- Birleştirilmiş sonuçlarını okumanız gerekmiyorsa önceki Döngü düğümünde çıktı toplamayı kapatın.
Sonuç boyutu
Kod düğümleri dahil her iş akışı düğümü çıktısı 25 MB ile sınırlıdır. Kodunuzun döndürdüğü sonuç 25 MB’ı aşarsa düğüm Node output exceeded the maximum size of 25 MB. Reduce the amount of data the node returns (e.g. filter or paginate results). hatasıyla başarısız olur ve aşırı büyük sonuç saklanmaz. Bu JavaScript ve Python için geçerlidir. Bir files dizisinde döndürdüğünüz veya Python çalışma dizininde oluşturduğunuz dosyalar çıktı ölçülmeden önce yüklenir; bu nedenle içerikleri limite sayılmaz.
JavaScript sonuçları ayrıca kod yürütme hizmetinden geçer; bu hizmet satır içi döndürülen dosyalar dahil tam yanıtını 150 MB ile sınırlar. Ayrıntılar için Sandbox yardımcı işlevleri sayfasına bakın.
Her iki limite de takılırsanız yalnızca sonraki düğümlerin ihtiyaç duyduğu alanları döndürün ve büyük veri kümelerini döndürmeden önce filtreleyin veya sayfalayın.
Sonraki adımlar
- Ajan — Akıllı işleme için yapay zeka kullanın
- HTTP isteği — Harici veri getirin
- Veri analizi — Bir Ajan ile veri analiz edin