ztools-guide
Skill1 starsChanged 7 months agoMITView on GitHub
Guides how to integrate the zTools package for ChatGPT, DALL-E image generation, file upload (S3), slug generation, email sending, and document validation in a .NET 8 project. Use when the user wants to use AI features, upload files, generate slugs, send emails, or understand zTools integration.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- emaginebr/AvaBotword for word, first seen Apr 8, 2026
Other versions1 project uses a version of this.
Word for word · 1
- emaginebr/AvaBot★ 2100% same
Edited · 0
None found.
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository39 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- readme-generatorSkill
- add-react-i18nSkill
- band-album-campaignSkill
- band-music-reflectionSkill
- band-streaming-launchSkill
- ckm:banner-designSkill
- ckm:brandSkill
- deploy-prodSkill
- ckm:designSkill
- ckm:design-systemSkill
- docker-compose-configSkill
- doc-managerSkill
- dotnet-architectureSkill
- dotnet-doc-controllerSkill
- dotnet-envSkill
- dotnet-fluent-validationSkill
- dotnet-graphqlSkill
- dotnet-multi-tenantSkill
- dotnet-test-apiSkill
- dotnet-testSkill
- frontend-designSkill
- gitversionSkill
- maui-architectureSkill
- mermaid-chartSkill
- nauth-guideSkill
- nnews-guideSkill
- react-alertSkill
- react-architectureSkill
- react-archSkill
- react-modalSkill
- readme-generatorSkill
- ckm:slidesSkill
- social-media-assetsSkill
- social-media-schedulingSkill
- social-post-authoringSkill
- ckm:ui-stylingSkill
- ui-ux-pro-maxSkill
- wsl-dockerSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 4 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 15
If no argument is provided, present a complete overview of the zTools integration.
- Distinctive: line 17
When the user asks about zTools, use this knowledge base to provide accurate, contextual guidance.
- Distinctive: line 391
Context-aware: If in NNews project, reference existing files (ArticleAIService.cs, ImageController.cs, TagService.cs)
- Distinctive: line 392
Minimal changes: Only suggest what's needed for the user's question
- Very specific: line 393
DALL-E: Always remind about temporary URLs needing persistence via IFileClient
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
zTools Integration Guide
You are an expert assistant that helps developers integrate the zTools NuGet package for utility services (ChatGPT, DALL-E, file storage, slug generation, email, document validation) in .NET 8 Web API projects.
Input
The user may provide a specific question or context as argument: $ARGUMENTS
If no argument is provided, present a complete overview of the zTools integration.
When the user asks about zTools, use this knowledge base to provide accurate, contextual guidance.
zTools — Data Transfer Objects
Install: dotnet add package zTools --version 0.3.1
Settings
public class zToolsetting { public string ApiUrl { get; set; } }
public class ChatGPTSetting { public string ApiUrl; public string ApiKey; public string Model; }
public class MailerSendSetting { /* MailerSend API config */ }
public class S3Setting { /* S3 bucket, credentials, endpoint config */ }ChatGPT DTOs
public class ChatMessage
{
public string Role { get; set; } // "system", "user", or "assistant"
public string Content { get; set; }
}
public class ChatGPTRequest { public string Model; public List<ChatMessage> Messages; }
public class ChatGPTResponse { public List<ChatGPTChoice> Choices; public ChatGPTUsage Usage; }
public class ChatGPTMessageRequest { public string Message; }
public class ChatGPTErrorResponse { /* Error handling */ }DALL-E DTOs
public class DallERequest
{
public string Prompt { get; set; } // Image description
public string Model { get; set; } // "dall-e-3"
public string Size { get; set; } // "1024x1024", "1024x1792", "1792x1024"
public string Quality { get; set; } // "standard" or "hd"
public string Style { get; set; } // "vivid" or "natural"
}
public class DallEResponse { public List<DallEImageData> Data; }
public class DallEImageData { public string Url; public string RevisedPrompt; }Email DTOs
public class MailerInfo { /* Email composition and sending */ }
public class MailerRecipientInfo { /* Recipient info */ }
public class MailerErrorInfo { /* Error handling */ }zTools — Anti-Corruption Layer
Install: dotnet add package zTools --version 0.3.1
IChatGPTClient
public interface IChatGPTClient
{
Task<string> SendMessageAsync(string question);
Task<string> SendConversationAsync(List<ChatMessage> messages);
Task<DallEResponse> GenerateImageAdvancedAsync(DallERequest request);
}IStringClient
public interface IStringClient
{
Task<string> GenerateSlugAsync(string text); // "Hello World!" -> "hello-world"
}IFileClient
public interface IFileClient
{
Task<string> UploadFileAsync(string bucketName, IFormFile file); // Returns file name
Task<string> GetFileUrlAsync(string bucketName, string fileName); // Returns public URL
}IMailClient / IDocumentClient
public interface IMailClient { /* Email validation and sending via MailerSend */ }
public interface IDocumentClient { /* CPF/CNPJ validation */ }Implementations: ChatGPTClient, StringClient, FileClient, MailClient, DocumentClient.
Step-by-Step Integration
1. Configure appsettings.json
{
"zTools": {
"ApiURL": "http://localhost:5001"
}
}Docker: use "ApiURL": "http://ztools-api:80".
2. Register Services (DI)
using zTools.ACL;
using zTools.ACL.Interfaces;
using zTools.DTO.Settings;
services.Configure<zToolsetting>(configuration.GetSection("zTools"));
services.AddHttpClient();
// Register only the clients you need
services.AddScoped<IChatGPTClient, ChatGPTClient>(); // ChatGPT + DALL-E
services.AddScoped<IStringClient, StringClient>(); // Slug generation
services.AddScoped<IFileClient, FileClient>(); // File upload/retrieval
services.AddScoped<IMailClient, MailClient>(); // Email sending
services.AddScoped<IDocumentClient, DocumentClient>(); // Document validationUsage Examples
ChatGPT — Simple Question
public async Task<string> AskQuestion(string question)
{
return await _chatGPTClient.SendMessageAsync(question);
}ChatGPT — Conversation with System Prompt
using zTools.DTO.ChatGPT;
public async Task<string> GenerateContent(string userPrompt)
{
var messages = new List<ChatMessage>
{
new ChatMessage { Role = "system", Content = "You are a content writer. Return only valid JSON." },
new ChatMessage { Role = "user", Content = userPrompt }
};
var response = await _chatGPTClient.SendConversationAsync(messages);
// Clean markdown wrapper if present
var clean = response.Trim();
if (clean.StartsWith("```json"))
{
clean = clean.Substring(7);
if (clean.EndsWith("```"))
clean = clean.Substring(0, clean.Length - 3);
clean = clean.Trim();
}
return clean;
}ChatGPT — Multi-turn Conversation
var messages = new List<ChatMessage>
{
new ChatMessage { Role = "system", Content = "You are a helpful assistant." },
new ChatMessage { Role = "user", Content = "What is .NET?" },
new ChatMessage { Role = "assistant", Content = ".NET is a free, open-source developer platform..." },
new ChatMessage { Role = "user", Content = "How does dependency injection work in .NET?" }
};
var response = await _chatGPTClient.SendConversationAsync(messages);DALL-E 3 — Image Generation
public async Task<string?> GenerateImage(string description)
{
var request = new DallERequest
{
Prompt = description,
Model = "dall-e-3",
Size = "1024x1024",
Quality = "standard",
Style = "vivid"
};
var response = await _chatGPTClient.GenerateImageAdvancedAsync(request);
if (response?.Data == null || !response.Data.Any())
return null;
return response.Data.First().Url; // Temporary URL — must persist!
}DALL-E 3 — Generate, Download and Upload to S3
Important: DALL-E returns temporary URLs. Always download and re-upload to your own storage.
public async Task<string?> GenerateAndUploadImage(string imagePrompt)
{
// 1. Generate image
var imageResponse = await _chatGPTClient.GenerateImageAdvancedAsync(new DallERequest
{
Prompt = imagePrompt, Model = "dall-e-3",
Size = "1024x1024", Quality = "standard", Style = "vivid"
});
if (imageResponse?.Data == null || !imageResponse.Data.Any())
return null;
var imageUrl = imageResponse.Data.First().Url;
if (string.IsNullOrWhiteSpace(imageUrl)) return null;
// 2. Download temporary image
var imageBytes = await _httpClient.GetByteArrayAsync(imageUrl);
// 3. Upload to S3
var fileName = $"ai-generated-{Guid.NewGuid()}.png";
using var stream = new MemoryStream(imageBytes);
IFormFile formFile = new FormFileWrapper(stream, fileName, "image/png");
var uploadedName = await _fileClient.UploadFileAsync("MyBucket", formFile);
return await _fileClient.GetFileUrlAsync("MyBucket", uploadedName);
}File Upload — Controller
[Route("api/[controller]")]
[ApiController]
public class ImageController : ControllerBase
{
private readonly IFileClient _fileClient;
public ImageController(IFileClient fileClient) { _fileClient = fileClient; }
[RequestSizeLimit(100_000_000)]
[HttpPost("upload")]
[Authorize]
public async Task<ActionResult<string>> Upload(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("No file uploaded");
var fileName = await _fileClient.UploadFileAsync("MyBucket", file);
var url = await _fileClient.GetFileUrlAsync("MyBucket", fileName);
return Ok(url);
}
}Slug Generation with Collision Detection
public async Task<string> GenerateUniqueSlug(string title, Func<string, bool> slugExists)
{
string slug;
int counter = 0;
do
{
slug = await _stringClient.GenerateSlugAsync(title);
if (counter > 0) slug += counter.ToString(); // "my-slug", "my-slug1", "my-slug2"
counter++;
} while (slugExists(slug));
return slug;
}FormFileWrapper (for programmatic uploads)
internal class FormFileWrapper : IFormFile
{
private readonly Stream _stream;
private readonly string _fileName;
private readonly string _contentType;
public FormFileWrapper(Stream stream, string fileName, string contentType)
{ _stream = stream; _fileName = fileName; _contentType = contentType; }
public string ContentType => _contentType;
public string ContentDisposition => $"form-data; name=\"file\"; filename=\"{_fileName}\"";
public IHeaderDictionary Headers => new HeaderDictionary();
public long Length => _stream.Length;
public string Name => "file";
public string FileName => _fileName;
public void CopyTo(Stream target) => _stream.CopyTo(target);
public Task CopyToAsync(Stream target, CancellationToken ct = default) => _stream.CopyToAsync(target, ct);
public Stream OpenReadStream() => _stream;
}Common Patterns
AI Content Generation with Structured JSON
public async Task<MyDto> GenerateWithAI(string prompt)
{
var messages = new List<ChatMessage>
{
new ChatMessage { Role = "system", Content = "Return ONLY valid JSON: {\"title\":\"\",\"body\":\"\",\"tags\":\"\"}" },
new ChatMessage { Role = "user", Content = prompt }
};
var response = await _chatGPTClient.SendConversationAsync(messages);
// Strip markdown wrapper, then deserialize
var clean = response.Trim();
if (clean.StartsWith("```json")) { clean = clean[7..]; if (clean.EndsWith("```")) clean = clean[..^3]; clean = clean.Trim(); }
return JsonSerializer.Deserialize<MyDto>(clean, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
}Combined AI + Image + Storage Pipeline
public async Task<ArticleResult> CreateArticleWithAI(string prompt, bool withImage)
{
var content = await GenerateWithAI(prompt);
string? imageUrl = null;
if (withImage && !string.IsNullOrEmpty(content.ImagePrompt))
imageUrl = await GenerateAndUploadImage(content.ImagePrompt);
var slug = await _stringClient.GenerateSlugAsync(content.Title);
return new ArticleResult { Title = content.Title, Content = content.Body, Slug = slug, ImageUrl = imageUrl };
}Troubleshooting
| Issue | Cause | Solution |
| ChatGPT returns empty | zTools API unreachable | Verify zTools:ApiURL in appsettings |
| DALL-E URL expired | Temporary URLs not persisted | Download and re-upload to S3 via IFileClient |
GenerateSlugAsync empty | Empty input | Validate input before calling |
| File upload fails | File too large | Add [RequestSizeLimit] to controller |
| DI error | Missing registration | Add services.AddScoped<IChatGPTClient, ChatGPTClient>() |
| JSON wrapped in markdown | ChatGPT formatting | Strip ```json / ``` before deserializing |
| Slug collision | Duplicate in DB | Use retry loop with counter suffix |
Response Guidelines
- Be specific: Reference exact class names, interfaces, and method signatures
- Show code: Include working examples based on the patterns above
- Context-aware: If in NNews project, reference existing files (ArticleAIService.cs, ImageController.cs, TagService.cs)
- Minimal changes: Only suggest what's needed for the user's question
- DALL-E: Always remind about temporary URLs needing persistence via
IFileClient
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

